Maybe accept invites more reliably
This commit is contained in:
@@ -230,7 +230,7 @@ async function createRoom(channel, guild, spaceID, kstate, privacyLevel) {
|
|||||||
|
|
||||||
db.transaction(() => {
|
db.transaction(() => {
|
||||||
db.prepare("INSERT INTO channel_room (channel_id, room_id, name, nick, thread_parent) VALUES (?, ?, ?, NULL, ?)").run(channel.id, roomID, channel.name, threadParent)
|
db.prepare("INSERT INTO channel_room (channel_id, room_id, name, nick, thread_parent) VALUES (?, ?, ?, NULL, ?)").run(channel.id, roomID, channel.name, threadParent)
|
||||||
db.prepare("INSERT INTO historical_channel_room (channel_id, room_id) VALUES (?, ?)").run(channel.id, roomID)
|
db.prepare("INSERT INTO historical_channel_room (reference_channel_id, room_id) VALUES (?, ?)").run(channel.id, roomID)
|
||||||
})()
|
})()
|
||||||
|
|
||||||
return roomID
|
return roomID
|
||||||
@@ -571,6 +571,7 @@ module.exports.createAllForGuild = createAllForGuild
|
|||||||
module.exports.channelToKState = channelToKState
|
module.exports.channelToKState = channelToKState
|
||||||
module.exports.postApplyPowerLevels = postApplyPowerLevels
|
module.exports.postApplyPowerLevels = postApplyPowerLevels
|
||||||
module.exports._convertNameAndTopic = convertNameAndTopic
|
module.exports._convertNameAndTopic = convertNameAndTopic
|
||||||
|
module.exports._syncSpaceMember = _syncSpaceMember
|
||||||
module.exports.unbridgeChannel = unbridgeChannel
|
module.exports.unbridgeChannel = unbridgeChannel
|
||||||
module.exports.unbridgeDeletedChannel = unbridgeDeletedChannel
|
module.exports.unbridgeDeletedChannel = unbridgeDeletedChannel
|
||||||
module.exports.existsOrAutocreatable = existsOrAutocreatable
|
module.exports.existsOrAutocreatable = existsOrAutocreatable
|
||||||
|
|||||||
@@ -322,14 +322,25 @@ sync.addTemporaryListener(as, "type:m.room.member", guard("m.room.member",
|
|||||||
*/
|
*/
|
||||||
async event => {
|
async event => {
|
||||||
if (event.state_key[0] !== "@") return
|
if (event.state_key[0] !== "@") return
|
||||||
|
const bot = `@${reg.sender_localpart}:${reg.ooye.server_name}`
|
||||||
|
|
||||||
if (event.content.membership === "invite" && event.state_key === `@${reg.sender_localpart}:${reg.ooye.server_name}`) {
|
if (event.content.membership === "invite" && event.state_key === bot) {
|
||||||
// We were invited to a room. We should join, and register the invite details for future reference in web.
|
// We were invited to a room. We should join, and register the invite details for future reference in web.
|
||||||
|
let attemptedApiMessage = "According to unsigned invite data."
|
||||||
|
let inviteRoomState = event.unsigned?.invite_room_state
|
||||||
|
if (!Array.isArray(inviteRoomState) || inviteRoomState.length === 0) {
|
||||||
|
try {
|
||||||
|
inviteRoomState = await api.getInviteState(event.room_id)
|
||||||
|
attemptedApiMessage = "According to SSS API."
|
||||||
|
} catch (e) {
|
||||||
|
attemptedApiMessage = "According to unsigned invite data. SSS API unavailable: " + e.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
const name = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.name", "name")
|
const name = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.name", "name")
|
||||||
const topic = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.topic", "topic")
|
const topic = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.topic", "topic")
|
||||||
const avatar = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.avatar", "url")
|
const avatar = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.avatar", "url")
|
||||||
const creationType = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.create", "type")
|
const creationType = getFromInviteRoomState(event.unsigned?.invite_room_state, "m.room.create", "type")
|
||||||
if (!name) return await api.leaveRoomWithReason(event.room_id, "Please only invite me to rooms that have a name/avatar set. Update the room details and reinvite!")
|
if (!name) return await api.leaveRoomWithReason(event.room_id, `Please only invite me to rooms that have a name/avatar set. Update the room details and reinvite! (${attemptedApiMessage})`)
|
||||||
await api.joinRoom(event.room_id)
|
await api.joinRoom(event.room_id)
|
||||||
db.prepare("INSERT OR IGNORE INTO invite (mxid, room_id, type, name, topic, avatar) VALUES (?, ?, ?, ?, ?, ?)").run(event.sender, event.room_id, creationType, name, topic, avatar)
|
db.prepare("INSERT OR IGNORE INTO invite (mxid, room_id, type, name, topic, avatar) VALUES (?, ?, ?, ?, ?, ?)").run(event.sender, event.room_id, creationType, name, topic, avatar)
|
||||||
if (avatar) utils.getPublicUrlForMxc(avatar) // make sure it's available in the media_proxy allowed URLs
|
if (avatar) utils.getPublicUrlForMxc(avatar) // make sure it's available in the media_proxy allowed URLs
|
||||||
@@ -342,7 +353,6 @@ async event => {
|
|||||||
db.prepare("DELETE FROM member_cache WHERE room_id = ? and mxid = ?").run(event.room_id, event.state_key)
|
db.prepare("DELETE FROM member_cache WHERE room_id = ? and mxid = ?").run(event.room_id, event.state_key)
|
||||||
|
|
||||||
// Unregister room's use as a direct chat if the bot itself left
|
// Unregister room's use as a direct chat if the bot itself left
|
||||||
const bot = `@${reg.sender_localpart}:${reg.ooye.server_name}`
|
|
||||||
if (event.state_key === bot) {
|
if (event.state_key === bot) {
|
||||||
db.prepare("DELETE FROM direct WHERE room_id = ?").run(event.room_id)
|
db.prepare("DELETE FROM direct WHERE room_id = ?").run(event.room_id)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,24 @@ function getStateEvent(roomID, type, key) {
|
|||||||
return mreq.mreq("GET", `/client/v3/rooms/${roomID}/state/${type}/${key}`)
|
return mreq.mreq("GET", `/client/v3/rooms/${roomID}/state/${type}/${key}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} roomID
|
||||||
|
* @returns {Promise<Ty.Event.InviteStrippedState[]>}
|
||||||
|
*/
|
||||||
|
async function getInviteState(roomID) {
|
||||||
|
/** @type {Ty.R.SSS} */
|
||||||
|
const root = await mreq.mreq("POST", "/client/unstable/org.matrix.simplified_msc3575/sync", {
|
||||||
|
room_subscriptions: {
|
||||||
|
[roomID]: {
|
||||||
|
timeline_limit: 0,
|
||||||
|
required_state: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const roomResponse = root.rooms[roomID]
|
||||||
|
return "stripped_state" in roomResponse ? roomResponse.stripped_state : roomResponse.invite_state
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Any of the AS's users must be in the room. This API is primarily for Application Services and should be faster to respond than /members as it can be implemented more efficiently on the server."
|
* "Any of the AS's users must be in the room. This API is primarily for Application Services and should be faster to respond than /members as it can be implemented more efficiently on the server."
|
||||||
* @param {string} roomID
|
* @param {string} roomID
|
||||||
@@ -483,6 +501,7 @@ module.exports.getEvent = getEvent
|
|||||||
module.exports.getEventForTimestamp = getEventForTimestamp
|
module.exports.getEventForTimestamp = getEventForTimestamp
|
||||||
module.exports.getAllState = getAllState
|
module.exports.getAllState = getAllState
|
||||||
module.exports.getStateEvent = getStateEvent
|
module.exports.getStateEvent = getStateEvent
|
||||||
|
module.exports.getInviteState = getInviteState
|
||||||
module.exports.getJoinedMembers = getJoinedMembers
|
module.exports.getJoinedMembers = getJoinedMembers
|
||||||
module.exports.getMembers = getMembers
|
module.exports.getMembers = getMembers
|
||||||
module.exports.getHierarchy = getHierarchy
|
module.exports.getHierarchy = getHierarchy
|
||||||
|
|||||||
81
src/types.d.ts
vendored
81
src/types.d.ts
vendored
@@ -166,6 +166,37 @@ export namespace Event {
|
|||||||
content: any
|
content: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type InviteStrippedState = {
|
||||||
|
type: string
|
||||||
|
state_key: string
|
||||||
|
sender: string
|
||||||
|
content: Event.M_Room_Create | Event.M_Room_Name | Event.M_Room_Avatar | Event.M_Room_Topic | Event.M_Room_JoinRules | Event.M_Room_CanonicalAlias
|
||||||
|
}
|
||||||
|
|
||||||
|
export type M_Room_Create = {
|
||||||
|
additional_creators: string[]
|
||||||
|
"m.federate"?: boolean
|
||||||
|
room_version: string
|
||||||
|
type?: string
|
||||||
|
predecessor?: {
|
||||||
|
room_id: string
|
||||||
|
event_id?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type M_Room_JoinRules = {
|
||||||
|
join_rule: "public" | "knock" | "invite" | "private" | "restricted" | "knock_restricted"
|
||||||
|
allow?: {
|
||||||
|
type: string
|
||||||
|
room_id: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type M_Room_CanonicalAlias = {
|
||||||
|
alias?: string
|
||||||
|
alt_aliases?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
export type M_Room_Message = {
|
export type M_Room_Message = {
|
||||||
msgtype: "m.text" | "m.emote"
|
msgtype: "m.text" | "m.emote"
|
||||||
body: string
|
body: string
|
||||||
@@ -375,7 +406,57 @@ export namespace R {
|
|||||||
room_id: string
|
room_id: string
|
||||||
servers: string[]
|
servers: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SSS = {
|
||||||
|
pos: string
|
||||||
|
lists: {
|
||||||
|
[list_key: string]: {
|
||||||
|
count: number
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
rooms: {
|
||||||
|
[room_id: string]: {
|
||||||
|
bump_stamp: number
|
||||||
|
/** Omitted if user not in room (peeking) */
|
||||||
|
membership?: Membership
|
||||||
|
/** Names of lists that match this room */
|
||||||
|
lists: string[]
|
||||||
|
}
|
||||||
|
// If user has been in the room - at least, that's what the spec says. Synapse returns some of these, such as `name` and `avatar`, for invites as well. Go nuts.
|
||||||
|
& {
|
||||||
|
name?: string
|
||||||
|
avatar?: string
|
||||||
|
heroes?: any[]
|
||||||
|
/** According to account data */
|
||||||
|
is_dm?: boolean
|
||||||
|
/** If false, omitted fields are unchanged from their previous value. If true, omitted fields means the fields are not set. */
|
||||||
|
initial?: boolean
|
||||||
|
expanded_timeline?: boolean
|
||||||
|
required_state?: Event.StateOuter<any>[]
|
||||||
|
timeline_events?: Event.Outer<any>[]
|
||||||
|
prev_batch?: string
|
||||||
|
limited?: boolean
|
||||||
|
num_live?: number
|
||||||
|
joined_count?: number
|
||||||
|
invited_count?: number
|
||||||
|
notification_count?: number
|
||||||
|
highlight_count?: number
|
||||||
|
}
|
||||||
|
// If user is invited or knocked
|
||||||
|
& ({
|
||||||
|
/** @deprecated */
|
||||||
|
invite_state: Event.InviteStrippedState[]
|
||||||
|
} | {
|
||||||
|
stripped_state: Event.InviteStrippedState[]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
extensions: {
|
||||||
|
[extension_key: string]: any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Membership = "invite" | "knock" | "join" | "leave" | "ban"
|
||||||
|
|
||||||
export type Pagination<T> = {
|
export type Pagination<T> = {
|
||||||
chunk: T[]
|
chunk: T[]
|
||||||
|
|||||||
Reference in New Issue
Block a user