Add decodo screenshot command#6
Conversation
- Introduced a new `screenshot` command to capture PNG screenshots of specified URLs. - Implemented options for geo targeting and output file specification. - Added utility functions for handling binary output and extracting PNG data from responses. - Updated command registration to include the new `createScreenshotCommand`. - Enhanced tests to cover the new screenshot command functionality and validation scenarios.
| @@ -0,0 +1,5 @@ | |||
| export interface ScreenshotOptions { | |||
| country?: string; | |||
| output?: string; | |||
There was a problem hiding this comment.
Are you sure all three are optional?
There was a problem hiding this comment.
Yes, this mirrors command options:
.option("--country <code>", "Geo / country code (maps to geo)")
.option("-o, --output <path>", "Write PNG to file instead of stdout")
.option("--target <name>", "Scrape target override (default: universal)")
output is only needed when stdout is a TTY
country and target have defaults in the command action (resolveTarget defaults to universal; geo is omitted if unset)
| } | ||
|
|
||
| export function extractPngFromResponse(response: SyncResponse): Buffer { | ||
| const entry = response.results[0]; |
There was a problem hiding this comment.
What if result will be empty.
There was a problem hiding this comment.
This is handled in this check:
if (entry === undefined) {
throw new ValidationError("Screenshot response has no results.");
}
| @@ -0,0 +1,30 @@ | |||
| import type { Command } from "commander"; | |||
|
|
|||
| export const ROOT_COMMAND_ORDER = [ | |||
There was a problem hiding this comment.
Not sure if possible, but maybe we can create groups, like:
User:
- setup;
- reset;
- etc;
Scrape:
- scrape;
- search;
- screenshot
- etc;
and when you will use --help it shows as grouped commands.
There was a problem hiding this comment.
The code is more about sorting commands which favor top level over target specific ones. Grouping is possible and can be done but I think it's product desicion, separate task
| }, | ||
| (response, options) => { | ||
| const opts = options as ScreenshotOptions; | ||
| writeBinaryOutput(extractPngFromResponse(response), { |
There was a problem hiding this comment.
What about filename? Maybe we should have option for this too.
There was a problem hiding this comment.
-o, --output already accepts a full file path (see line 16). If filename only variant is needed it can be added but I think the full path covers that use case
There was a problem hiding this comment.
good point, with previous changes it just throws which is bad ux, if folder is specified then by default it will save to a predefined filepath, updated pr description on how it works with new changes
| const orderIndex = new Map(order.map((name, index) => [name, index])); | ||
| const fallbackIndex = order.length; | ||
|
|
||
| return [...commands].sort((a, b) => { | ||
| const aIndex = orderIndex.get(a.name()) ?? fallbackIndex; | ||
| const bIndex = orderIndex.get(b.name()) ?? fallbackIndex; | ||
|
|
||
| if (aIndex !== bIndex) { | ||
| return aIndex - bIndex; | ||
| } | ||
|
|
||
| return a.name().localeCompare(b.name()); |
There was a problem hiding this comment.
I'm having a hard time understanding reasoning here, but as I've understand the idea is to have ROOT_COMMAND_ORDER as first commands, then everything else?
There was a problem hiding this comment.
Yes, you go it right. Not sure how to better write this, since there is no option for sort order in commander. Maybe better would be to have an export SORT_ORDER = ... for each command but that still requires a registry to map all the commands so it's kind of the same as it is right now
…pport - Added functionality to specify a directory for output files in the screenshot command, defaulting to a generated filename based on the URL hostname. - Refactored binary output handling to support writing to files or directories. - Introduced utility functions for resolving output file paths and generating default screenshot filenames. - Updated tests to validate new directory output behavior and filename generation. - Removed obsolete `write-binary.ts` file and migrated its functionality to a new service.
Summary
Adds
decodo screenshotfor PNG captures via the universal target withheadless: png. Builds on the tier-1 scrape/search stack in the base branch.decodo screenshot <url>—-o/--outputwrites a PNG file; pipe to stdout when not a TTY (refuses binary on TTY without-o)-ofile or directory — if the path is an existing directory, writes<host>.pngderived from the URL (fallbackscreenshot.png); explicit file paths unchangedWrote <absolute path>on stderr after a successful file writeextractPngFromResponse— base64 fromresults[0].content, PNG signature validationplatform/services/—writeBinaryOutputandresolveOutputFilePathfor shared binary stdout and-opath resolution;defaultScreenshotFilenamestays inscrape/services/run-target-scrapeinservices/with optionalonResponsehandler (passes scrape input for screenshot filename); scrape/search behavior unchangedscreenshotlisted aftersearchin root--helpTest plan
pnpm testdecodo screenshot https://ip.decodo.com -o shot.png(stderr showsWrote …)decodo screenshot https://ip.decodo.com -o ./shots→./shots/ip.decodo.com.pngdecodo screenshot https://ip.decodo.com > shot.png(non-TTY)decodo screenshot <url>on TTY without-oshows usage error