2121__all__ = ('LinkFix' ,)
2222
2323_logger = logging .getLogger (__name__ )
24+ WEBHOOK_NAME = "FixTweetBot"
2425
2526
2627def get_website (guild : Guild , url : str , spoiler : bool = False ) -> WebsiteLink | None :
@@ -136,7 +137,13 @@ async def fix_embeds(
136137 or (isinstance (channel , discore .Thread ) and (channel .locked or channel .archived ))):
137138 return
138139
139- async with Typing (channel ):
140+ if not guild .reply_as_original_sender_profile :
141+ async with Typing (channel ):
142+ rendered_links = [link for link in links if await link .render ()]
143+ if not rendered_links :
144+ return
145+ not_sent , messages = await send_fixed_links (rendered_links , guild , original_message )
146+ else :
140147 rendered_links = [link for link in links if await link .render ()]
141148 if not rendered_links :
142149 return
@@ -200,9 +207,15 @@ async def send_fixed_links(
200207 links_failed : list [tuple [str , list [WebsiteLink ]]] = []
201208
202209 grouped = group_items (rendered_links , 2000 )
210+ use_original_sender_profile = guild .reply_as_original_sender_profile
211+ webhook = await get_or_create_webhook (original_message .channel ) if use_original_sender_profile else None
212+ if use_original_sender_profile and webhook is None :
213+ return [(message_content , links_in_group ) for message_content , links_in_group in grouped ], messages_sent
203214
204215 for i , (message_content , links_in_group ) in enumerate (grouped ):
205- if i == 0 and guild .reply_to_message :
216+ if webhook is not None :
217+ coro = webhook_send (webhook , original_message , message_content , guild .reply_silently )
218+ elif i == 0 and guild .reply_to_message :
206219 coro = discore .fallback_reply (original_message , message_content , silent = guild .reply_silently )
207220 else :
208221 coro = original_message .channel .send (message_content , silent = guild .reply_silently )
@@ -216,6 +229,64 @@ async def send_fixed_links(
216229 return links_failed , messages_sent
217230
218231
232+ async def get_or_create_webhook (channel : discore .TextChannel | discore .Thread ) -> discore .Webhook | None :
233+ """
234+ Get or create the webhook used to send messages as the original sender.
235+
236+ :param channel: the channel to send the fixed links to
237+ :return: the webhook to use, if available
238+ """
239+
240+ webhook_channel = channel .parent if isinstance (channel , discore .Thread ) else channel
241+ if webhook_channel is None :
242+ return None
243+
244+ if not webhook_channel .permissions_for (channel .guild .me ).manage_webhooks :
245+ return None
246+
247+ try :
248+ webhooks = await webhook_channel .webhooks ()
249+ except discore .HTTPException :
250+ _logger .exception ("Failed to fetch webhooks" )
251+ return None
252+ webhook = next ((
253+ w for w in webhooks
254+ if w .name == WEBHOOK_NAME and getattr (w .user , 'id' , None ) == channel .guild .me .id
255+ ), None )
256+ if webhook is not None :
257+ return webhook
258+ sent , webhook = await safe_send_coro (webhook_channel .create_webhook (name = WEBHOOK_NAME ), forbidden = True )
259+ return webhook if sent else None
260+
261+
262+ async def webhook_send (
263+ webhook : discore .Webhook ,
264+ original_message : discore .Message ,
265+ content : str ,
266+ silent : bool
267+ ) -> discore .Message :
268+ """
269+ Send a fixed link using the original sender's display name and avatar.
270+
271+ :param webhook: the webhook to use
272+ :param original_message: the message associated with the context to reply to
273+ :param content: the content to send
274+ :param silent: whether to send the message silently
275+ :return: the message created by the webhook
276+ """
277+
278+ kwargs = {
279+ 'content' : content ,
280+ 'username' : original_message .author .display_name ,
281+ 'avatar_url' : original_message .author .display_avatar .url ,
282+ 'silent' : silent ,
283+ 'wait' : True
284+ }
285+ if isinstance (original_message .channel , discore .Thread ):
286+ kwargs ['thread' ] = original_message .channel
287+ return await webhook .send (** kwargs )
288+
289+
219290async def wait_for_embed (message : discore .Message ) -> bool :
220291 """
221292 Wait for the message to have embeds.
0 commit comments