@@ -144,6 +144,9 @@ async def _to_beacon_content(self, message: discord.Message) -> beacon_message.B
144144 results = await asyncio .gather (* tasks , return_exceptions = True )
145145 files : list [beacon_file .BeaconFile ] = [result for result in results if type (result ) is beacon_file .BeaconFile ]
146146
147+ # Get pin status
148+ is_pin : bool = message .type == discord .MessageType .pins_add
149+
147150 # Assemble blocks
148151 blocks : dict [str , beacon_content .BeaconContentBlock ] = {
149152 "content" : text_content
@@ -162,7 +165,8 @@ async def _to_beacon_content(self, message: discord.Message) -> beacon_message.B
162165 files = files ,
163166 replies = replies ,
164167 reply_content = self ._driver .sanitize_outbound (reply_content ) if reply_content else None ,
165- reply_attachments = reply_attachments
168+ reply_attachments = reply_attachments ,
169+ message_type = beacon_message .BeaconMessageType .pins_add if is_pin else None
166170 )
167171
168172 return content
@@ -294,11 +298,53 @@ async def handle_delete(self, message: discord.Message):
294298 except beacon .BeaconPlatformDisabled :
295299 pass
296300
301+ async def handle_pin (self , message : discord .Message ):
302+ # noinspection DuplicatedCode
303+ origin_driver : beacon_driver .BeaconDriver = self ._beacon .drivers .get_driver ("discord" )
304+
305+ # Get the BeaconMessage object for the message
306+ message_obj : beacon_message .BeaconMessage = self ._beacon .messages .get_message (str (message .id ))
307+ if not message_obj :
308+ # We can't pin messages that aren't cached
309+ return
310+
311+ # Convert guild data to server.BeaconServer
312+ server : beacon_server .BeaconServer = origin_driver .get_server (str (message .guild .id ))
313+
314+ # Convert channel data to channel.BeaconChannel
315+ # noinspection DuplicatedCode
316+ channel : beacon_channel .BeaconChannel = origin_driver .get_channel (server , str (message .channel .id ))
317+ if not channel :
318+ # We can't bridge
319+ return
320+
321+ # Get Space
322+ space : beacon_space .BeaconSpace = self ._beacon .spaces .get_space_for_channel (channel )
323+
324+ if not space :
325+ # We can't bridge pins, even if it was sent in the Space by the server
326+ return
327+
328+ # Pin the message!
329+ try :
330+ await self ._beacon .pin (message = message_obj , unpin = not message .pinned )
331+ except beacon .BeaconPlatformDisabled :
332+ pass
333+
297334 @commands .Cog .listener ()
298335 async def on_message (self , message : discord .Message ):
299336 origin_driver : beacon_driver .BeaconDriver = self ._beacon .drivers .get_driver ("discord" )
300337
301- # noinspection DuplicatedCode
338+ supported_types : list [discord .MessageType ] = [
339+ discord .MessageType .default ,
340+ discord .MessageType .reply ,
341+ discord .MessageType .pins_add
342+ ]
343+ supported_types_community : list [discord .MessageType ] = [
344+ discord .MessageType .default ,
345+ discord .MessageType .reply
346+ ]
347+
302348 if message .content .startswith (self .bot .command_prefix ):
303349 # Assume this is a text command
304350 return
@@ -307,6 +353,11 @@ async def on_message(self, message: discord.Message):
307353 # Do not self-bridge
308354 return
309355
356+ if message .type not in supported_types :
357+ # Unsupported message
358+ return
359+
360+ # noinspection DuplicatedCode
310361 if message .webhook_id :
311362 # Check if the webhook was ours (to prevent a self-bridge)
312363 webhook : discord .Webhook | None = origin_driver .webhooks .get_webhook (str (message .webhook_id ))
@@ -386,14 +437,38 @@ async def on_message(self, message: discord.Message):
386437 pass
387438
388439 @commands .Cog .listener ()
389- async def on_message_edit (self , _ , message : discord .Message ):
440+ async def on_message_edit (self , before : discord .Message , message : discord .Message ):
441+ # Identify update type
442+ is_pin : bool = before .pinned != message .pinned
443+
390444 # Check if message is pending
391445 if self ._beacon .is_pending (str (message .id )):
392446 # Add callback
393- self ._beacon .add_callback (str (message .id ), self .handle_edit , [message ])
447+ if is_pin :
448+ self ._beacon .add_callback (str (message .id ), self .handle_pin , [message ])
449+ else :
450+ self ._beacon .add_callback (str (message .id ), self .handle_edit , [message ])
451+ else :
452+ # Run directly
453+ if is_pin :
454+ await self .handle_pin (message )
455+ else :
456+ await self .handle_edit (message )
457+
458+ @commands .Cog .listener ()
459+ async def on_raw_message_edit (self , payload : discord .RawMessageUpdateEvent ):
460+ # Do not handle cached messages (on_message_edit does this for us)
461+ if payload .cached_message :
462+ return
463+
464+ # For uncached messages, we can only handle content edits for now. This may change in a future update
465+ # Check if message is pending
466+ if self ._beacon .is_pending (str (payload .new_message .id )):
467+ # Add callback
468+ self ._beacon .add_callback (str (payload .new_message .id ), self .handle_edit , [payload .new_message ])
394469 else :
395470 # Run directly
396- await self .handle_edit (message )
471+ await self .handle_edit (payload . new_message )
397472
398473 @commands .Cog .listener ()
399474 async def on_message_delete (self , message : discord .Message ):
0 commit comments