-
Notifications
You must be signed in to change notification settings - Fork 1
Add SinkingYachts realtime feed integration #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,123 @@ | ||||||||||||||||||||||||
import express, { Request, Response } from "express"; | ||||||||||||||||||||||||
import { sinkingYahtsService } from "src/services/_index"; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
const router = express.Router(); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
/** | ||||||||||||||||||||||||
* POST /admin/sinking-yachts/start-feed | ||||||||||||||||||||||||
* @summary Starts the SinkingYachts realtime feed monitoring | ||||||||||||||||||||||||
* @tags SinkingYachts - Feed Management | ||||||||||||||||||||||||
* @security BearerAuth | ||||||||||||||||||||||||
* @param {object} request.body | ||||||||||||||||||||||||
* @param {boolean} request.body.skipBulkImport - Skip the initial bulk import (optional) | ||||||||||||||||||||||||
* @return {object} 200 - Success response | ||||||||||||||||||||||||
* @return {object} 500 - Error response | ||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||
router.post("/start-feed", async (req: Request, res: Response) => { | ||||||||||||||||||||||||
try { | ||||||||||||||||||||||||
const { skipBulkImport = false } = req.body; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
await sinkingYahtsService.startFeedMonitoring(skipBulkImport); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return res.status(200).json({ | ||||||||||||||||||||||||
success: true, | ||||||||||||||||||||||||
message: "SinkingYachts feed monitoring started successfully", | ||||||||||||||||||||||||
skipBulkImport | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} catch (error: any) { | ||||||||||||||||||||||||
return res.status(500).json({ | ||||||||||||||||||||||||
success: false, | ||||||||||||||||||||||||
message: "Failed to start SinkingYachts feed monitoring", | ||||||||||||||||||||||||
error: error.message | ||||||||||||||||||||||||
Comment on lines
+27
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using 'any' type for error handling reduces type safety. Consider using 'Error | unknown' or create a specific error type for better type checking.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
Comment on lines
+27
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The return res.status(500).json({
success: false,
message: "Failed to start SinkingYachts feed monitoring",
error: error instanceof Error ? error.message : String(error)
}); |
||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
/** | ||||||||||||||||||||||||
* POST /admin/sinking-yachts/stop-feed | ||||||||||||||||||||||||
* @summary Stops the SinkingYachts realtime feed monitoring | ||||||||||||||||||||||||
* @tags SinkingYachts - Feed Management | ||||||||||||||||||||||||
* @security BearerAuth | ||||||||||||||||||||||||
* @return {object} 200 - Success response | ||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||
router.post("/stop-feed", async (req: Request, res: Response) => { | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||
try { | ||||||||||||||||||||||||
sinkingYahtsService.stopRealtimeFeed(); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return res.status(200).json({ | ||||||||||||||||||||||||
success: true, | ||||||||||||||||||||||||
message: "SinkingYachts feed monitoring stopped successfully" | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} catch (error: any) { | ||||||||||||||||||||||||
return res.status(500).json({ | ||||||||||||||||||||||||
success: false, | ||||||||||||||||||||||||
message: "Failed to stop SinkingYachts feed monitoring", | ||||||||||||||||||||||||
error: error.message | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
/** | ||||||||||||||||||||||||
* POST /admin/sinking-yachts/bulk-import | ||||||||||||||||||||||||
* @summary Manually triggers a bulk import of all domains from SinkingYachts | ||||||||||||||||||||||||
* @tags SinkingYachts - Feed Management | ||||||||||||||||||||||||
* @security BearerAuth | ||||||||||||||||||||||||
* @return {object} 200 - Success response | ||||||||||||||||||||||||
* @return {object} 500 - Error response | ||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||
router.post("/bulk-import", async (req: Request, res: Response) => { | ||||||||||||||||||||||||
try { | ||||||||||||||||||||||||
await sinkingYahtsService.initializeBulkImport(); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return res.status(200).json({ | ||||||||||||||||||||||||
success: true, | ||||||||||||||||||||||||
message: "SinkingYachts bulk import completed successfully" | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} catch (error: any) { | ||||||||||||||||||||||||
return res.status(500).json({ | ||||||||||||||||||||||||
success: false, | ||||||||||||||||||||||||
message: "Failed to complete SinkingYachts bulk import", | ||||||||||||||||||||||||
error: error.message | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
/** | ||||||||||||||||||||||||
* GET /admin/sinking-yachts/recent | ||||||||||||||||||||||||
* @summary Fetches recent domains from SinkingYachts API | ||||||||||||||||||||||||
* @tags SinkingYachts - Feed Management | ||||||||||||||||||||||||
* @security BearerAuth | ||||||||||||||||||||||||
* @param {string} since.query.required - ISO date string for filtering recent domains | ||||||||||||||||||||||||
* @return {object} 200 - Array of recent domains | ||||||||||||||||||||||||
* @return {object} 400 - Bad request (missing since parameter) | ||||||||||||||||||||||||
* @return {object} 500 - Error response | ||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||
router.get("/recent", async (req: Request, res: Response) => { | ||||||||||||||||||||||||
try { | ||||||||||||||||||||||||
const { since } = req.query; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
if (!since || typeof since !== "string") { | ||||||||||||||||||||||||
return res.status(400).json({ | ||||||||||||||||||||||||
success: false, | ||||||||||||||||||||||||
message: "Missing or invalid 'since' query parameter (ISO date string required)" | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
const recentDomains = await sinkingYahtsService.getRecentDomains(since); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return res.status(200).json({ | ||||||||||||||||||||||||
success: true, | ||||||||||||||||||||||||
data: recentDomains, | ||||||||||||||||||||||||
count: recentDomains.length, | ||||||||||||||||||||||||
since | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} catch (error: any) { | ||||||||||||||||||||||||
return res.status(500).json({ | ||||||||||||||||||||||||
success: false, | ||||||||||||||||||||||||
message: "Failed to fetch recent domains", | ||||||||||||||||||||||||
error: error.message | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
export default router; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -11,6 +11,7 @@ import { server } from "./server"; | |||||
// import metrics from "./metrics"; | ||||||
import { swaggerOptions as adminSwagOptions } from "./admin-routes/swaggerOptions"; | ||||||
import { swaggerOptions as mainSwagOptions } from "./swaggerOptions"; | ||||||
import { sinkingYahtsService } from "./services/_index"; | ||||||
import * as logger from "./utils/logger"; | ||||||
dotenv.config(); | ||||||
|
||||||
|
@@ -26,6 +27,21 @@ try { | |||||
} | ||||||
const db = drizzle(process.env.DATABASE_URL); | ||||||
logger.database("Database connection initialized successfully"); | ||||||
|
||||||
// Initialize SinkingYachts realtime feed monitoring | ||||||
if (process.env.ENABLE_SINKING_YACHTS_FEED !== "false") { | ||||||
logger.info("Starting SinkingYachts realtime feed monitoring..."); | ||||||
sinkingYahtsService.startFeedMonitoring(process.env.SKIP_BULK_IMPORT === "true") | ||||||
.then(() => { | ||||||
logger.info("SinkingYachts feed monitoring started successfully"); | ||||||
}) | ||||||
.catch((error) => { | ||||||
logger.error(`Failed to start SinkingYachts feed monitoring: ${error.message}`); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||
// Don't exit the process, let the server continue without feed monitoring | ||||||
}); | ||||||
} else { | ||||||
logger.info("SinkingYachts feed monitoring disabled by ENABLE_SINKING_YACHTS_FEED=false"); | ||||||
} | ||||||
} catch (error) { | ||||||
logger.error( | ||||||
`Failed to initialize database connection: ${error instanceof Error ? error.message : String(error)}` | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify WebSocket library versions and security status
Please ensure these versions are the latest stable releases and free from known vulnerabilities.
Also applies to: 64-64
🏁 Script executed:
Length of output: 1813
Update
ws
and@types/ws
to the latest stable releasesThe
ws
package at ^8.18.0 already includes the DoS fix patched in 8.17.1, so it’s no longer vulnerable, but the current latest is 8.18.3. Similarly,@types/ws
is at 8.5.13 while the latest is 8.18.1. For best compatibility and to pick up any minor fixes:• package.json (line 51): update
• package.json (line 64): update
📝 Committable suggestion
🤖 Prompt for AI Agents