1- import { ApplicationCommandMessage } from "@fire/lib/extensions/appcommandmessage" ;
21import { ContextCommandMessage } from "@fire/lib/extensions/contextcommandmessage" ;
3- import { FireMember } from "@fire/lib/extensions/guildmember " ;
2+ import { FireGuild } from "@fire/lib/extensions/guild " ;
43import { FireMessage } from "@fire/lib/extensions/message" ;
54import { MessageContextMenuInteraction } from "@fire/lib/extensions/messagecontextmenuinteraction" ;
6- import { FireUser } from "@fire/lib/extensions/user" ;
7- import { PartialQuoteDestination } from "@fire/lib/interfaces/messages" ;
5+ import {
6+ MessageLinkMatch ,
7+ PartialQuoteDestination ,
8+ } from "@fire/lib/interfaces/messages" ;
89import { Command } from "@fire/lib/util/command" ;
910import { GuildTextChannel , constants } from "@fire/lib/util/constants" ;
11+ import { messageConverter } from "@fire/lib/util/converters" ;
1012import { Language } from "@fire/lib/util/language" ;
11- import { ThreadhookClient } from "@fire/lib/util/threadhookclient" ;
13+ import { Message } from "@fire/lib/ws/Message" ;
14+ import { EventType } from "@fire/lib/ws/util/constants" ;
15+ import { MessageUtil } from "@fire/lib/ws/util/MessageUtil" ;
1216import { Snowflake } from "discord-api-types/globals" ;
1317import { PermissionFlagsBits } from "discord-api-types/v9" ;
1418import {
1519 Collection ,
1620 Constants ,
1721 GuildChannelResolvable ,
22+ GuildTextBasedChannel ,
1823 MessageActionRow ,
1924 MessageButton ,
20- MessageEmbed ,
2125} from "discord.js" ;
2226
2327const { regexes } = constants ;
@@ -47,6 +51,8 @@ export default class Quote extends Command {
4751 context : [ "save to quote" ] ,
4852 restrictTo : "all" , // required for context cmd
4953 ephemeral : true , // context only
54+ slashOnly : true ,
55+ hidden : true ,
5056 } ) ;
5157
5258 this . savedQuotes = new Collection ( ) ;
@@ -57,71 +63,128 @@ export default class Quote extends Command {
5763 } , 30000 ) ;
5864 }
5965
60- async exec (
61- message ?: FireMessage ,
62- args ?: {
63- destination ?: PartialQuoteDestination ;
64- quoter ?: FireMember | FireUser ;
65- quote ?: FireMessage ;
66- webhook ?: string ;
67- debug ?: boolean ;
68- }
66+ async handleLocalQuote (
67+ message : FireMessage ,
68+ match : MessageLinkMatch ,
69+ debug = false // TODO: reimplement debug messages
6970 ) {
70- if (
71- message &&
72- ! message . guild &&
73- ! message . author . hasExperiment ( 3069732134 , 1 )
74- )
75- return await message . error ( "COMMAND_GUILD_ONLY" , {
76- invite : this . client . config . inviteLink ,
77- } ) ;
78- if ( ! args ?. quote ) return ;
79- let debugMessages : string [ ] ;
80- if ( args . debug ) debugMessages = [ ] ;
81- let webhook : ThreadhookClient ;
82- if ( args . webhook ) {
83- const match = regexes . discord . webhook . exec ( args . webhook ) ;
84- regexes . discord . webhook . lastIndex = 0 ;
85- if ( ! match ?. groups . id || ! match ?. groups . token ) return ;
86- webhook = new ThreadhookClient (
87- { id : match . groups . id as Snowflake , token : match . groups . token } ,
88- { threadId : match . groups . threadId as Snowflake }
71+ const convertedMessage = await messageConverter (
72+ message ,
73+ null ,
74+ debug ,
75+ match
76+ ) . catch ( ( ) => { } ) ;
77+ if ( ! convertedMessage ) return ;
78+ else if (
79+ convertedMessage . reference ?. type == Constants . MessageReferenceType . FORWARD
80+ ) {
81+ const { reference } = convertedMessage ;
82+ const shard = this . client . util . getShard ( reference . guildId ) ;
83+ if ( ! ( this . client . options . shards as number [ ] ) . includes ( shard ) )
84+ return this . forwardCrossClusterQuote ( message , {
85+ guild_id : reference . guildId ,
86+ channel_id : reference . channelId ,
87+ message_id : reference . messageId ,
88+ } ) ;
89+ const guild = this . client . guilds . cache . get (
90+ reference . guildId
91+ ) as FireGuild ;
92+ if ( ! guild ) return ;
93+ const channel = guild . channels . cache . get (
94+ reference . channelId
95+ ) as GuildTextBasedChannel ;
96+ if ( ! channel ) return ;
97+ const referencedMessage = ( await channel . messages
98+ . fetch ( reference . messageId )
99+ . catch ( ( ) => { } ) ) as FireMessage ;
100+ if ( ! referencedMessage ) return ;
101+ else
102+ return await referencedMessage . quote (
103+ channel ,
104+ message . member ?? message . author
105+ ) ;
106+ } else {
107+ await convertedMessage . quote (
108+ message . channel as GuildTextBasedChannel ,
109+ message . member ?? message . author
89110 ) ;
90- return await args . quote
91- . quote ( args . destination , args . quoter , webhook , debugMessages )
92- . catch ( ( ) => { } ) ;
111+ if ( match . iteratedMessages ?. length )
112+ for ( const iterated of match . iteratedMessages )
113+ await iterated . quote (
114+ message . channel as GuildTextBasedChannel ,
115+ message . member ?? message . author
116+ ) ;
93117 }
94- if ( ! message ) return ; // we shouldn't get here without one
95- if ( args . quote . content . length > 2000 )
96- return await message . error ( QUOTE_PREMIUM_INCREASED_LENGTH ) ;
97- const quoted = await args . quote
98- . quote (
99- message instanceof ApplicationCommandMessage
100- ? ( message . realChannel as GuildTextChannel )
101- : ( message . channel as GuildTextChannel ) ,
102- message . member ?? message . author ,
103- webhook ,
104- debugMessages
118+ }
119+
120+ async forwardCrossClusterQuote (
121+ message : FireMessage ,
122+ quote : MessageLinkMatch
123+ ) {
124+ const shard = this . client . util . getShard ( quote . guild_id ) ;
125+ const webhook = await this . client . util . getQuoteWebhookURL (
126+ message . channel as GuildTextChannel
127+ ) ;
128+ if ( ! webhook ?. token ) return ;
129+ this . console . log ( "Forwarding cross-cluster quote" , {
130+ user : `${ message . author } (${ message . author . id } )` ,
131+ guild : `${ message . guild } (${ message . guild . id } )` ,
132+ source : `${ quote . guild_id } /${ quote . channel_id } /${ quote . message_id } ` ,
133+ destination : `${ message . guild . id } /${ message . channelId } ` ,
134+ shard,
135+ } ) ;
136+ this . client . manager . ws . send (
137+ MessageUtil . encode (
138+ new Message ( EventType . CROSS_CLUSTER_QUOTE , {
139+ shard,
140+ quoter : message . author . id ,
141+ webhook,
142+ message : quote ,
143+ destination : {
144+ nsfw : ( message . channel as GuildTextChannel ) ?. nsfw || false ,
145+ permissions : message . guild
146+ ? message . member ?. permissions . bitfield . toString ( ) || "0"
147+ : "0" ,
148+ guild_id : message . guild ?. id ,
149+ id : message . channelId ,
150+ } as PartialQuoteDestination ,
151+ } )
105152 )
106- . catch ( ( e : Error ) =>
107- ( args . quoter ?? message . author ) . isSuperuser ( ) ? e . stack : e . message
108- ) ;
109- if ( quoted == QUOTE_PREMIUM_INCREASED_LENGTH )
110- return await message . error ( quoted ) ;
111- else if ( quoted == "nsfw" ) return await message . error ( "QUOTE_NSFW_TO_SFW" ) ;
112- else if ( quoted == "empty" )
113- return await message . error ( "QUOTE_MISSING_CONTENT" ) ;
114- if ( typeof quoted == "string" && debugMessages ) debugMessages . push ( quoted ) ;
115- if ( args . debug ) {
116- if ( ! debugMessages . length ) return ;
117- const content = debugMessages . join ( "\n" ) ;
118- if ( content . length > 2000 && content . length < 4096 )
119- return await message . channel . send ( {
120- embeds : [ new MessageEmbed ( ) . setDescription ( content ) ] ,
121- } ) ;
122- else if ( content . length <= 2000 )
123- return await message . channel . send ( content ) ;
153+ ) ;
154+ }
155+
156+ returnCrossClusterQuote (
157+ destination : PartialQuoteDestination ,
158+ quote : MessageLinkMatch ,
159+ quoter : Snowflake ,
160+ webhook : {
161+ id : Snowflake ;
162+ token : string ;
163+ threadId ?: Snowflake ;
124164 }
165+ ) {
166+ if ( ! webhook ?. token ) return ;
167+
168+ const shard = this . client . util . getShard ( destination . guild_id ) ;
169+ this . console . log (
170+ "Returning cross cluster quote due to forwarded message on another cluster" ,
171+ {
172+ quoter,
173+ quote,
174+ shard,
175+ }
176+ ) ;
177+ this . client . manager . ws . send (
178+ MessageUtil . encode (
179+ new Message ( EventType . CROSS_CLUSTER_QUOTE , {
180+ shard,
181+ quoter,
182+ webhook,
183+ message : quote ,
184+ destination,
185+ } )
186+ )
187+ ) ;
125188 }
126189
127190 // Slash & Context commands will always try Command#run first
0 commit comments