@@ -27,6 +27,7 @@ func SendPhaseFiles(phaseName, domain string, filePaths []string) error {
2727 // Get channel ID and scan ID from environment (set by bot)
2828 channelID := os .Getenv ("AUTOAR_CURRENT_CHANNEL_ID" )
2929 scanID := os .Getenv ("AUTOAR_CURRENT_SCAN_ID" )
30+ threadID := os .Getenv ("AUTOAR_CURRENT_THREAD_ID" )
3031
3132 // Debug logs only (not sent to webhook)
3233 log .Printf ("[DEBUG] [DISCORD] Attempting to send phase files for phase: %s, domain: %s" , phaseName , domain )
@@ -77,7 +78,11 @@ func SendPhaseFiles(phaseName, domain string, filePaths []string) error {
7778 if len (existingFiles ) == 0 {
7879 log .Printf ("[DEBUG] [DISCORD] No valid files to send for phase %s" , phaseName )
7980 msg := phaseNoResultsMessage (phaseName , domain )
80- SendWebhookLogAsync (msg )
81+
82+ if err := sendStringToDiscordHTTP (apiHost , apiPort , channelID , scanID , threadID , msg ); err != nil {
83+ log .Printf ("[DEBUG] [DISCORD] HTTP API message send failed: %v, falling back to webhook" , err )
84+ SendWebhookLogAsync (msg )
85+ }
8186 return nil
8287 }
8388
@@ -103,8 +108,8 @@ func SendPhaseFiles(phaseName, domain string, filePaths []string) error {
103108 }
104109
105110 // Send file (will use bot if available, otherwise webhook, even if no channel ID)
106- // sendSingleFileToDiscord handles webhook fallback when channelID is empty
107- if err := sendSingleFileToDiscordWithDescription (apiHost , apiPort , channelID , scanID , phaseName , filePath , description ); err != nil {
111+ // sendSingleFileToDiscordWithDescription handles webhook fallback when channelID is empty
112+ if err := sendSingleFileToDiscordWithDescription (apiHost , apiPort , channelID , scanID , threadID , filePath , description ); err != nil {
108113 log .Printf ("[DEBUG] [DISCORD] Failed to send file %s: %v" , fileName , err )
109114 failCount ++
110115 } else {
@@ -122,11 +127,49 @@ func SendPhaseFiles(phaseName, domain string, filePaths []string) error {
122127 return nil
123128}
124129
125- func sendSingleFileToDiscord (apiHost , apiPort , channelID , scanID , phaseName , filePath string ) error {
126- return sendSingleFileToDiscordWithDescription (apiHost , apiPort , channelID , scanID , phaseName , filePath , filepath .Base (filePath ))
130+ func sendStringToDiscordHTTP (apiHost , apiPort , channelID , scanID , threadID , message string ) error {
131+ if scanID == "" && channelID == "" {
132+ return fmt .Errorf ("no scan_id or channel_id provided" )
133+ }
134+
135+ reqBody := map [string ]string {
136+ "message" : message ,
137+ "channel_id" : channelID ,
138+ }
139+ if scanID != "" {
140+ reqBody ["scan_id" ] = scanID
141+ }
142+ if threadID != "" {
143+ reqBody ["thread_id" ] = threadID
144+ }
145+
146+ jsonData , err := json .Marshal (reqBody )
147+ if err != nil {
148+ return err
149+ }
150+
151+ url := fmt .Sprintf ("http://%s:%s/internal/send-message" , apiHost , apiPort )
152+ req , err := http .NewRequest ("POST" , url , bytes .NewBuffer (jsonData ))
153+ if err != nil {
154+ return err
155+ }
156+ req .Header .Set ("Content-Type" , "application/json" )
157+
158+ client := & http.Client {Timeout : 10 * time .Second }
159+ resp , err := client .Do (req )
160+ if err != nil {
161+ return err
162+ }
163+ defer resp .Body .Close ()
164+
165+ if resp .StatusCode == http .StatusOK {
166+ return nil
167+ }
168+ bodyBytes , _ := io .ReadAll (resp .Body )
169+ return fmt .Errorf ("API returned status %d: %s" , resp .StatusCode , string (bodyBytes ))
127170}
128171
129- func sendSingleFileToDiscordWithDescription (apiHost , apiPort , channelID , scanID , phaseName , filePath , description string ) error {
172+ func sendSingleFileToDiscordWithDescription (apiHost , apiPort , channelID , scanID , threadID , filePath , description string ) error {
130173
131174 // If channel ID is provided, try bot first (for Discord bot context)
132175 // If no channel ID (CLI usage), skip bot and go straight to HTTP API/webhook
@@ -162,6 +205,9 @@ func sendSingleFileToDiscordWithDescription(apiHost, apiPort, channelID, scanID,
162205 reqBody ["scan_id" ] = scanID
163206 log .Printf ("[DEBUG] [DISCORD] Including scan_id in HTTP API request: %s" , scanID )
164207 }
208+ if threadID != "" {
209+ reqBody ["thread_id" ] = threadID
210+ }
165211
166212 jsonData , err := json .Marshal (reqBody )
167213 if err == nil {
0 commit comments