| 105 | if (!media) return false; |
| 106 | const cn = media.className || media._ || ""; |
| 107 | if (!cn || cn === "MessageMediaEmpty") return false; |
| 108 | return true; |
| 109 | } |
| 110 | |
| 111 | function isFinalBotMessage(msg: Api.Message): boolean { |
| 112 | // Media always wins — bot may edit progress text in place while attaching file |
| 113 | if (hasMediaPayload(msg)) return true; |
| 114 | const text = msg.message?.trim() || ""; |
| 115 | if (isProgressText(text)) return false; |
| 116 | return Boolean(text); |
| 117 | } |
| 118 | |
| 119 | function extractLinks(text: string): string[] { |
| 120 | if (!text) return []; |
| 121 | const matches = text.match(/(?:https?:\/\/|www\.)\S+/gi) || []; |
| 122 | const sanitized = matches.map((raw) => { |
| 123 | const cleaned = raw.replace( |