Compare commits
7
Commits
1147091a18
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7902b91c38 | ||
|
|
c196bef0ba | ||
|
|
f39a7f4251 | ||
|
|
f19f24314a | ||
|
|
08dea68e46 | ||
|
|
a4f8f93ad9 | ||
|
|
9d7f8888a7 |
Generated
+6
-20
@@ -57,19 +57,6 @@
|
|||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../discord-markdown": {
|
|
||||||
"name": "@cloudrac3r/discord-markdown",
|
|
||||||
"version": "2.9.0",
|
|
||||||
"extraneous": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"simple-markdown": "^0.7.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@cloudrac3r/tap-dot": "^2.0.2",
|
|
||||||
"supertape": "^13.6.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||||
@@ -146,9 +133,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudrac3r/discord-markdown": {
|
"node_modules/@cloudrac3r/discord-markdown": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudrac3r/discord-markdown/-/discord-markdown-2.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudrac3r/discord-markdown/-/discord-markdown-2.9.1.tgz",
|
||||||
"integrity": "sha512-0S22mNlT9rPhYnxP+qzKWayVe+hFWcEqxVCviF/pyzWAb9nLaBZkIVk0jHTImoA1MY0mqx1uMKjIcxVHkEZe3A==",
|
"integrity": "sha512-sYaDfRBaS7uMVQx4wJwT68F6OzJZX84DF2XvHkQr8vdwTCvnpeaT26obqvzNawVwVoQ4xjIMZxafgMrAEK4Oxw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"simple-markdown": "^0.7.3"
|
"simple-markdown": "^0.7.3"
|
||||||
@@ -283,9 +270,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cloudrac3r/tell-me-when": {
|
"node_modules/@cloudrac3r/tell-me-when": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@cloudrac3r/tell-me-when/-/tell-me-when-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@cloudrac3r/tell-me-when/-/tell-me-when-2.0.1.tgz",
|
||||||
"integrity": "sha512-U+TEOTe6f/vSIeD/QP0VPrkLrhnFtQs2euxBOAaqC8rzQKu8nNoKSFuhipT6DyuCZH48B58+qrPMmH2w2IgMhA==",
|
"integrity": "sha512-nm1Ao/vpHDn2YMivnc9EVr/QrcT5IG6G7o1Ffh31YafIo9Cc3bSN1jPLL9eOuKKLCYT1/DZP7Nh8PXAN371bAQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tell-me-when": "dist/src/cli.js"
|
"tell-me-when": "dist/src/cli.js"
|
||||||
@@ -1175,7 +1162,6 @@
|
|||||||
"version": "13.0.3",
|
"version": "13.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.3.tgz",
|
||||||
"integrity": "sha512-RbOBxmLBG8uvFUc15X9+9SFemKcQ0WBuISBVkpuiaUB2qblC8UWlHEjdWVoZ8AdhSwmoEgsiXKfopX0CQxaACQ==",
|
"integrity": "sha512-RbOBxmLBG8uvFUc15X9+9SFemKcQ0WBuISBVkpuiaUB2qblC8UWlHEjdWVoZ8AdhSwmoEgsiXKfopX0CQxaACQ==",
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-addon-api": "^8.0.0"
|
"node-addon-api": "^8.0.0"
|
||||||
|
|||||||
@@ -71,5 +71,8 @@
|
|||||||
"addbot": "node addbot.js",
|
"addbot": "node addbot.js",
|
||||||
"test": "cross-env FORCE_COLOR=true supertape --no-check-assertions-count --format tap --no-worker test/test.js | tap-dot",
|
"test": "cross-env FORCE_COLOR=true supertape --no-check-assertions-count --format tap --no-worker test/test.js | tap-dot",
|
||||||
"cover": "c8 -o test/coverage --skip-full -x db/migrations -x src/m2d/event-dispatcher.js -x src/matrix/file.js -x src/matrix/api.js -x src/d2m/converters/rlottie-wasm.js -r html -r text supertape --no-check-assertions-count --format fail --no-worker test/test.js -- --slow"
|
"cover": "c8 -o test/coverage --skip-full -x db/migrations -x src/m2d/event-dispatcher.js -x src/matrix/file.js -x src/matrix/api.js -x src/d2m/converters/rlottie-wasm.js -r html -r text supertape --no-check-assertions-count --format fail --no-worker test/test.js -- --slow"
|
||||||
|
},
|
||||||
|
"allowScripts": {
|
||||||
|
"better-sqlite3": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -915,8 +915,8 @@ async function messageToEvent(message, guild, options = {}, di) {
|
|||||||
|
|
||||||
// Add time
|
// Add time
|
||||||
if (event.scheduled_end_time) {
|
if (event.scheduled_end_time) {
|
||||||
const formatter = new Intl.DateTimeFormat("en-NZ", {month: "long", day: "numeric", hour: "numeric", minute: "2-digit", timeZoneName: "shortGeneric", timeZone: reg.ooye.time_zone}) // 9 June at 3:00 pm NZT
|
const formatter = new Intl.DateTimeFormat("en-NZ", {weekday: "long", month: "long", day: "numeric", hour: "numeric", minute: "2-digit", timeZone: "UTC"}) // 9 June at 3:00 pm NZT
|
||||||
var displayTime = formatter.formatRange(new Date(event.scheduled_start_time), new Date(event.scheduled_end_time))
|
var displayTime = (formatter.formatRange(new Date(event.scheduled_start_time), new Date(event.scheduled_end_time)) + " (UTC)").replaceAll(/\p{Zs}/gv, " ")
|
||||||
} else {
|
} else {
|
||||||
var displayTime = discordTime.convertDiscordTime(unixSeconds, "F")
|
var displayTime = discordTime.convertDiscordTime(unixSeconds, "F")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1589,12 +1589,12 @@ test("message2event: irl invite event renders embed", async t => {
|
|||||||
{
|
{
|
||||||
$type: "m.room.message",
|
$type: "m.room.message",
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: `| Scheduled Event - 8 June at 10:00 pm NZT – 9 June at 12:00 am NZT`
|
body: `| Scheduled Event - Sunday, 8 June, 10:00 am – 12:00 pm (UTC)`
|
||||||
+ `\n| ## forest exploration`
|
+ `\n| ## forest exploration`
|
||||||
+ `\n| `
|
+ `\n| `
|
||||||
+ `\n| 📍 the dark forest`,
|
+ `\n| 📍 the dark forest`,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
formatted_body: `<blockquote><p>Scheduled Event - 8 June at 10:00 pm NZT – 9 June at 12:00 am NZT</p>`
|
formatted_body: `<blockquote><p>Scheduled Event - <a href=\"https://bridge.example.org/time/1749376800/F\">Sunday, 8 June, 10:00 am – 12:00 pm (UTC)</a></p>`
|
||||||
+ `<strong>forest exploration</strong>`
|
+ `<strong>forest exploration</strong>`
|
||||||
+ `<p>📍 the dark forest</p></blockquote>`,
|
+ `<p>📍 the dark forest</p></blockquote>`,
|
||||||
"m.mentions": {}
|
"m.mentions": {}
|
||||||
@@ -1622,13 +1622,13 @@ test("message2event: vc invite event renders embed", async t => {
|
|||||||
{
|
{
|
||||||
$type: "m.room.message",
|
$type: "m.room.message",
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: `| Scheduled Event - 9 June at 3:00 pm NZT`
|
body: `| Scheduled Event - Monday, 9 June 2025 at 3:00 am (UTC)`
|
||||||
+ `\n| ## Cooking (Netrunners)`
|
+ `\n| ## Cooking (Netrunners)`
|
||||||
+ `\n| Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
+ `\n| Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
||||||
+ `\n| `
|
+ `\n| `
|
||||||
+ `\n| 🔊 Cooking`,
|
+ `\n| 🔊 Cooking`,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
formatted_body: `<blockquote><p>Scheduled Event - 9 June at 3:00 pm NZT</p>`
|
formatted_body: `<blockquote><p>Scheduled Event - <a href=\"https://bridge.example.org/time/1749438000/F\">Monday, 9 June 2025 at 3:00 am (UTC)</a></p>`
|
||||||
+ `<strong>Cooking (Netrunners)</strong><br>Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
+ `<strong>Cooking (Netrunners)</strong><br>Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
||||||
+ `<p>🔊 Cooking</p></blockquote>`,
|
+ `<p>🔊 Cooking</p></blockquote>`,
|
||||||
"m.mentions": {}
|
"m.mentions": {}
|
||||||
@@ -1664,13 +1664,13 @@ test("message2event: vc invite event renders embed with room link", async t => {
|
|||||||
{
|
{
|
||||||
$type: "m.room.message",
|
$type: "m.room.message",
|
||||||
msgtype: "m.notice",
|
msgtype: "m.notice",
|
||||||
body: `| Scheduled Event - 9 June at 3:00 pm NZT`
|
body: `| Scheduled Event - Monday, 9 June 2025 at 3:00 am (UTC)`
|
||||||
+ `\n| ## Cooking (Netrunners)`
|
+ `\n| ## Cooking (Netrunners)`
|
||||||
+ `\n| Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
+ `\n| Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
||||||
+ `\n| `
|
+ `\n| `
|
||||||
+ `\n| 🔊 Hey. - https://matrix.to/#/!FuDZhlOAtqswlyxzeR:cadence.moe?via=cadence.moe`,
|
+ `\n| 🔊 Hey. - https://matrix.to/#/!FuDZhlOAtqswlyxzeR:cadence.moe?via=cadence.moe`,
|
||||||
format: "org.matrix.custom.html",
|
format: "org.matrix.custom.html",
|
||||||
formatted_body: `<blockquote><p>Scheduled Event - 9 June at 3:00 pm NZT</p>`
|
formatted_body: `<blockquote><p>Scheduled Event - <a href=\"https://bridge.example.org/time/1749438000/F\">Monday, 9 June 2025 at 3:00 am (UTC)</a></p>`
|
||||||
+ `<strong>Cooking (Netrunners)</strong><br>Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
+ `<strong>Cooking (Netrunners)</strong><br>Short circuited brain interfaces actually just means your brain is medium rare, yum.`
|
||||||
+ `<p>🔊 Hey. - <a href="https://matrix.to/#/!FuDZhlOAtqswlyxzeR:cadence.moe?via=cadence.moe">Hey.</a></p></blockquote>`,
|
+ `<p>🔊 Hey. - <a href="https://matrix.to/#/!FuDZhlOAtqswlyxzeR:cadence.moe?via=cadence.moe">Hey.</a></p></blockquote>`,
|
||||||
"m.mentions": {}
|
"m.mentions": {}
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ function getFormatOptions(style) {
|
|||||||
function convertDiscordTime(timestamp, style) {
|
function convertDiscordTime(timestamp, style) {
|
||||||
const formatter = new Intl.DateTimeFormat("en-NZ", getFormatOptions(style))
|
const formatter = new Intl.DateTimeFormat("en-NZ", getFormatOptions(style))
|
||||||
const d = new Date(timestamp * 1000)
|
const d = new Date(timestamp * 1000)
|
||||||
return formatter.format(d) + " (UTC)"
|
return (formatter.format(d) + " (UTC)").replaceAll(/\p{Zs}/gv, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getFormatOptions = getFormatOptions
|
module.exports.getFormatOptions = getFormatOptions
|
||||||
|
|||||||
@@ -452,18 +452,18 @@ async function handleRoomOrMessageLinks(input, di) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} content
|
* @param {string} content
|
||||||
* @param {string} senderMxid
|
* @param {{content: any, room_id: string, sender: string}} event
|
||||||
* @param {string} roomID
|
|
||||||
* @param {DiscordTypes.APIGuild} guild
|
* @param {DiscordTypes.APIGuild} guild
|
||||||
* @param {{api: import("../../matrix/api"), snow: import("snowtransfer").SnowTransfer}} di
|
* @param {{api: import("../../matrix/api"), snow: import("snowtransfer").SnowTransfer}} di
|
||||||
*/
|
*/
|
||||||
async function checkWrittenMentions(content, senderMxid, roomID, guild, di) {
|
async function checkWrittenMentions(content, event, guild, di) {
|
||||||
let writtenMentionMatch = content.match(/(?:^|[^"[<>/A-Za-z0-9])@([A-Za-z][A-Za-z0-9._\[\]\(\)-]+):?/d) // /d flag for indices requires node.js 16+
|
let writtenMentionMatch = content.match(/(?:^|[^"[<>/A-Za-z0-9])@([A-Za-z][A-Za-z0-9._\[\]\(\)-]+):?/d) // /d flag for indices requires node.js 16+
|
||||||
if (writtenMentionMatch) {
|
if (writtenMentionMatch) {
|
||||||
if (writtenMentionMatch[1] === "room") { // convert @room to discord
|
if (writtenMentionMatch[1] === "room") { // convert @room to discord
|
||||||
const {powers: {[senderMxid]: userPower}, powerLevels} = await mxUtils.getEffectivePower(roomID, [senderMxid], di.api)
|
if (("m.mentions" in event.content) && !event.content["m.mentions"].room) return // check it's allowed by m.mentions if present
|
||||||
|
const {powers: {[event.sender]: userPower}, powerLevels} = await mxUtils.getEffectivePower(event.room_id, [event.sender], di.api)
|
||||||
if (userPower >= (powerLevels.notifications?.room ?? 50)) {
|
if (userPower >= (powerLevels.notifications?.room ?? 50)) {
|
||||||
const roleID = select("channel_room", "room_mention_role", {room_id: roomID}).pluck().get()
|
const roleID = select("channel_room", "room_mention_role", {room_id: event.room_id}).pluck().get()
|
||||||
return {
|
return {
|
||||||
// @ts-ignore - typescript doesn't know about indices yet
|
// @ts-ignore - typescript doesn't know about indices yet
|
||||||
content: content.slice(0, writtenMentionMatch.indices[1][0]-1) + (roleID ? `<@&${roleID}>` : "@everyone") + content.slice(writtenMentionMatch.indices[1][1]),
|
content: content.slice(0, writtenMentionMatch.indices[1][0]-1) + (roleID ? `<@&${roleID}>` : "@everyone") + content.slice(writtenMentionMatch.indices[1][1]),
|
||||||
@@ -914,7 +914,7 @@ async function eventToMessage(event, guild, channel, di) {
|
|||||||
|
|
||||||
// Check written mentions
|
// Check written mentions
|
||||||
if (node.nodeType === 3 && node.nodeValue.includes("@") && !nodeIsChildOf(node, ["A", "CODE", "PRE"])) {
|
if (node.nodeType === 3 && node.nodeValue.includes("@") && !nodeIsChildOf(node, ["A", "CODE", "PRE"])) {
|
||||||
const result = await checkWrittenMentions(node.nodeValue, event.sender, event.room_id, guild, di)
|
const result = await checkWrittenMentions(node.nodeValue, event, guild, di)
|
||||||
if (result) {
|
if (result) {
|
||||||
node.nodeValue = result.content
|
node.nodeValue = result.content
|
||||||
ensureJoined.push(...result.ensureJoined)
|
ensureJoined.push(...result.ensureJoined)
|
||||||
@@ -1032,7 +1032,7 @@ async function eventToMessage(event, guild, channel, di) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await checkWrittenMentions(content, event.sender, event.room_id, guild, di)
|
const result = await checkWrittenMentions(content, event, guild, di)
|
||||||
if (result) {
|
if (result) {
|
||||||
content = result.content
|
content = result.content
|
||||||
ensureJoined.push(...result.ensureJoined)
|
ensureJoined.push(...result.ensureJoined)
|
||||||
|
|||||||
@@ -5521,6 +5521,9 @@ test("event2message: @room converts to @everyone and is allowed when the room do
|
|||||||
type: "m.room.message",
|
type: "m.room.message",
|
||||||
sender: "@cadence:cadence.moe",
|
sender: "@cadence:cadence.moe",
|
||||||
content: {
|
content: {
|
||||||
|
"m.mentions": {
|
||||||
|
room: true
|
||||||
|
},
|
||||||
msgtype: "m.text",
|
msgtype: "m.text",
|
||||||
body: "@room dinner's ready",
|
body: "@room dinner's ready",
|
||||||
},
|
},
|
||||||
@@ -5563,7 +5566,124 @@ test("event2message: @room converts to @everyone and is allowed when the room do
|
|||||||
content: "@everyone dinner's ready",
|
content: "@everyone dinner's ready",
|
||||||
avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
|
avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
|
||||||
allowed_mentions: {
|
allowed_mentions: {
|
||||||
parse: ["users", "roles", "everyone"]
|
users: [],
|
||||||
|
parse: ["roles", "everyone"]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
ensureJoined: []
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("event2message: @room is converted to a role in configured rooms", async t => {
|
||||||
|
let called = 0
|
||||||
|
t.deepEqual(
|
||||||
|
await eventToMessage({
|
||||||
|
type: "m.room.message",
|
||||||
|
sender: "@cadence:cadence.moe",
|
||||||
|
content: {
|
||||||
|
msgtype: "m.text",
|
||||||
|
body: "@room dinner's ready",
|
||||||
|
},
|
||||||
|
room_id: "!fGgIymcYWOqjbSRUdV:cadence.moe",
|
||||||
|
event_id: "$SiXetU9h9Dg-M9Frcw_C6ahnoXZ3QPZe3MVJR5tcB9A"
|
||||||
|
}, data.guild.general, data.channel.general, {
|
||||||
|
api: {
|
||||||
|
async getStateEvent(roomID, type, key) {
|
||||||
|
called++
|
||||||
|
t.equal(roomID, "!fGgIymcYWOqjbSRUdV:cadence.moe")
|
||||||
|
t.equal(type, "m.room.power_levels")
|
||||||
|
t.equal(key, "")
|
||||||
|
return {
|
||||||
|
users: {},
|
||||||
|
notifications: {
|
||||||
|
room: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getStateEventOuter(roomID, type, key) {
|
||||||
|
t.equal(roomID, "!fGgIymcYWOqjbSRUdV:cadence.moe")
|
||||||
|
t.equal(type, "m.room.create")
|
||||||
|
t.equal(key, "")
|
||||||
|
return {
|
||||||
|
type: "m.room.create",
|
||||||
|
state_key: "",
|
||||||
|
sender: "@_ooye_bot:cadence.moe",
|
||||||
|
content: {
|
||||||
|
room_version: "11"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
messagesToDelete: [],
|
||||||
|
messagesToEdit: [],
|
||||||
|
messagesToSend: [{
|
||||||
|
username: "cadence [they]",
|
||||||
|
content: "<@&123456> dinner's ready",
|
||||||
|
avatar_url: "https://bridge.example.org/download/matrix/cadence.moe/azCAhThKTojXSZJRoWwZmhvU?preset=avatar",
|
||||||
|
allowed_mentions: {
|
||||||
|
parse: ["users", "roles"]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
ensureJoined: []
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("event2message: @room is not allowed with mismatched m.mentions", async t => {
|
||||||
|
let called = 0
|
||||||
|
t.deepEqual(
|
||||||
|
await eventToMessage({
|
||||||
|
type: "m.room.message",
|
||||||
|
sender: "@cadence:cadence.moe",
|
||||||
|
content: {
|
||||||
|
"m.mentions": {},
|
||||||
|
msgtype: "m.text",
|
||||||
|
body: "@room dinner's ready",
|
||||||
|
},
|
||||||
|
room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
|
||||||
|
event_id: "$SiXetU9h9Dg-M9Frcw_C6ahnoXZ3QPZe3MVJR5tcB9A"
|
||||||
|
}, data.guild.general, data.channel.general, {
|
||||||
|
api: {
|
||||||
|
async getStateEvent(roomID, type, key) {
|
||||||
|
called++
|
||||||
|
t.equal(roomID, "!kLRqKKUQXcibIMtOpl:cadence.moe")
|
||||||
|
t.equal(type, "m.room.power_levels")
|
||||||
|
t.equal(key, "")
|
||||||
|
return {
|
||||||
|
users: {},
|
||||||
|
notifications: {
|
||||||
|
room: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getStateEventOuter(roomID, type, key) {
|
||||||
|
t.equal(roomID, "!kLRqKKUQXcibIMtOpl:cadence.moe")
|
||||||
|
t.equal(type, "m.room.create")
|
||||||
|
t.equal(key, "")
|
||||||
|
return {
|
||||||
|
type: "m.room.create",
|
||||||
|
state_key: "",
|
||||||
|
sender: "@_ooye_bot:cadence.moe",
|
||||||
|
content: {
|
||||||
|
room_version: "11"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
messagesToDelete: [],
|
||||||
|
messagesToEdit: [],
|
||||||
|
messagesToSend: [{
|
||||||
|
username: "cadence [they]",
|
||||||
|
content: "@room dinner's ready",
|
||||||
|
avatar_url: "https://bridge.example.org/download/letter-avatar?letter=C&hue=90",
|
||||||
|
allowed_mentions: {
|
||||||
|
users: [],
|
||||||
|
parse: ["roles"]
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
ensureJoined: []
|
ensureJoined: []
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ html(lang="en")
|
|||||||
if style !== "R"
|
if style !== "R"
|
||||||
p #[span#remaining.remaining]#[span#direction] #[span#tick.tick]
|
p #[span#remaining.remaining]#[span#direction] #[span#tick.tick]
|
||||||
script.
|
script.
|
||||||
document.body.classList.add("yes-script")
|
|
||||||
const WIDTH = !{WIDTH}
|
const WIDTH = !{WIDTH}
|
||||||
const timestamp = !{timestamp}
|
const timestamp = !{timestamp}
|
||||||
const style = "!{style}"
|
const style = "!{style}"
|
||||||
@@ -104,6 +103,7 @@ html(lang="en")
|
|||||||
st.style.fontSize = Math.floor(parseInt(st.style.fontSize) * WIDTH / l) + "px";
|
st.style.fontSize = Math.floor(parseInt(st.style.fontSize) * WIDTH / l) + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
document.body.classList.add("yes-script")
|
||||||
|
|
||||||
let frame = 0
|
let frame = 0
|
||||||
function updateTimeRemaining() {
|
function updateTimeRemaining() {
|
||||||
@@ -116,15 +116,17 @@ html(lang="en")
|
|||||||
}
|
}
|
||||||
let difference = Math.abs(timeForRemaining.getTime() - now.getTime())
|
let difference = Math.abs(timeForRemaining.getTime() - now.getTime())
|
||||||
|
|
||||||
|
// Temporal.Duration isn't Baseline https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration
|
||||||
let foundSignificantField = false
|
let foundSignificantField = false
|
||||||
let remainingText = UNITS.map(([unit, duration], index) => {
|
const remainingTextParts = UNITS.map(([unit, duration], index) => {
|
||||||
const multiplier = Math.floor(difference / duration)
|
const multiplier = Math.floor(difference / duration)
|
||||||
difference -= multiplier * duration
|
difference -= multiplier * duration
|
||||||
if (multiplier > 0 || foundSignificantField) {
|
if (multiplier > 0 || foundSignificantField) {
|
||||||
foundSignificantField = true
|
foundSignificantField = true
|
||||||
return multiplier + "\u00a0" + unit + (multiplier !== 1 ? "s" : "")
|
return multiplier + "\u00a0" + unit + (multiplier !== 1 ? "s" : "")
|
||||||
}
|
}
|
||||||
}).filter(s => s).join(", ")
|
}).filter(s => s)
|
||||||
|
const remainingText = remainingTextParts.length === 2 ? remainingTextParts.join(" and ") : remainingTextParts.join(", ")
|
||||||
if (remainingText) {
|
if (remainingText) {
|
||||||
remaining.textContent = remainingText
|
remaining.textContent = remainingText
|
||||||
direction.textContent =
|
direction.textContent =
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
// Temporal API stabilised in Node.js 26. Previous versions can use `--harmony-temporal`, but that's jank, so have a polyfill.
|
// Ensure consistent output from the Intl and Temporal API across Node.js versions
|
||||||
if (!("Temporal" in globalThis)) {
|
require("temporal-polyfill-lite/global")
|
||||||
require("temporal-polyfill-lite/global")
|
|
||||||
}
|
|
||||||
|
|
||||||
const fs = require("fs")
|
const fs = require("fs")
|
||||||
const sqlite = require("better-sqlite3")
|
const sqlite = require("better-sqlite3")
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ INSERT INTO channel_room (channel_id, room_id, name, nick, thread_parent, custom
|
|||||||
('1161864271370666075', '!mHmhQQPwXNananMUqq:cadence.moe', 'updates', NULL, NULL, NULL, '112760669178241024'),
|
('1161864271370666075', '!mHmhQQPwXNananMUqq:cadence.moe', 'updates', NULL, NULL, NULL, '112760669178241024'),
|
||||||
('1438284564815548418', '!MHxNpwtgVqWOrmyoTn:cadence.moe', 'sin-cave', NULL, NULL, NULL, '665289423482519565'),
|
('1438284564815548418', '!MHxNpwtgVqWOrmyoTn:cadence.moe', 'sin-cave', NULL, NULL, NULL, '665289423482519565'),
|
||||||
('598707048112193536', '!JBxeGYnzQwLnaooOLD:cadence.moe', 'winners', NULL, NULL, NULL, '1345641201902288987');
|
('598707048112193536', '!JBxeGYnzQwLnaooOLD:cadence.moe', 'winners', NULL, NULL, NULL, '1345641201902288987');
|
||||||
|
UPDATE channel_room SET room_mention_role = '123456' WHERE room_id = '!fGgIymcYWOqjbSRUdV:cadence.moe';
|
||||||
|
|
||||||
INSERT INTO historical_channel_room (reference_channel_id, room_id, upgraded_timestamp) SELECT channel_id, room_id, 0 FROM channel_room;
|
INSERT INTO historical_channel_room (reference_channel_id, room_id, upgraded_timestamp) SELECT channel_id, room_id, 0 FROM channel_room;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
|
// Ensure consistent output from the Intl and Temporal API across Node.js versions
|
||||||
|
require("temporal-polyfill-lite/global")
|
||||||
|
|
||||||
const fs = require("fs")
|
const fs = require("fs")
|
||||||
const {join} = require("path")
|
const {join} = require("path")
|
||||||
const sqlite = require("better-sqlite3")
|
const sqlite = require("better-sqlite3")
|
||||||
|
|||||||
Reference in New Issue
Block a user