-
Notifications
You must be signed in to change notification settings - Fork 0
/
Scrape.hx
50 lines (46 loc) · 1.79 KB
/
Scrape.hx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using StringTools;
using sys.FileSystem;
class Scrape {
public static function main():Void {
function usage(?err:Bool = true):Void {
Sys.println("CTFd challenge scraper
Usage:
neko scrape.n --ctfd <API> <cookie> <output>
neko scrape.n --plaid <API> <cookie> <output>
Options:
<API> full URL to an API base (e.g. https://ctf.example.com/api/v1/)
<cookie> cookie used to authenticate (e.g ctfd=xyz;session=xyz)
<output> target file (e.g. README.md)
");
Sys.exit(err ? 1 : 0);
}
function err(str:String):Void {
Sys.println('error: $str
try \'neko scrape.n --help\' for usage');
Sys.exit(1);
}
switch (Sys.args()) {
case [apiType = ("--ctfd" | "--plaid"), api, cookie, output]:
if (!api.startsWith("https://") && !api.startsWith("http://")) err("API must be a full HTTP or HTTPS URL");
if (api.substr(api.length - 1, 1) == "/") api = api.substr(0, api.length - 1);
if (output.exists() && output.isDirectory()) err("output must not be an existing directory");
if (output.exists()) {
Sys.print("output file already exists, override? [y/N]: ");
switch (Sys.stdin().readLine().toLowerCase()) {
case "y" | "yes":
case _: Sys.exit(0);
}
}
if (!FileSystem.exists("cache")) FileSystem.createDirectory("cache");
var data = (try switch (apiType) {
case "--ctfd": CTFd.run(api, cookie);
case "--plaid": PlaidCTF.run(api, cookie);
case _: throw "unreachable";
} catch (ex:String) { err('error during retrieval: $ex'); null; });
Sys.println('${data.challenges.length} challenges found');
sys.io.File.saveContent(output, Writeup.format(data));
case ["--help"] | ["-?"] | ["-h"]: usage(false);
case _: usage();
}
}
}