1+ import std.net.curl ;
2+ import std.getopt ;
3+ import std.regex ;
4+ import std.stdio ;
5+ import std.json ;
6+ import std.conv ;
7+
8+ immutable BASE_URL = " https://api.github.com/users/" ;
9+
10+ struct GthUserItem {
11+ int count;
12+ string [] arr;
13+
14+ this (long count) {
15+ this .count = to! int (count);
16+ // The length will change later
17+ this .arr = new string [0 ];
18+ }
19+ }
20+
21+ class GthUser {
22+ private string url;
23+ private JSONValue obj;
24+
25+ string name;
26+ string bio;
27+ string link;
28+ GthUserItem repos;
29+ GthUserItem gists;
30+ GthUserItem followers;
31+ GthUserItem following;
32+
33+ this (string username) {
34+ this .url = BASE_URL ~ username;
35+
36+ auto res = get (this .url);
37+ this .obj = parseJSON(res);
38+
39+ this .name = this .obj[" name" ].str;
40+ this .bio = this .obj[" bio" ].str;
41+ this .link = this .obj[" html_url" ].str;
42+ this .repos = GthUserItem(this .obj[" public_repos" ].integer);
43+ this .gists = GthUserItem(this .obj[" public_gists" ].integer);
44+ this .followers = GthUserItem(this .obj[" followers" ].integer);
45+ this .following = GthUserItem(this .obj[" following" ].integer);
46+ }
47+
48+ void fetch (string thing) {
49+ auto url = this .url ~ ' /' ~ thing;
50+ auto res = get (url);
51+ auto arr = parseJSON(res).array;
52+
53+ switch (thing) {
54+ case " repos" :
55+ for (int i = 0 ; i < arr.length; i++ ) {
56+ this .repos.arr.length = arr.length;
57+ this .repos.arr[i] = arr[i][" name" ].str;
58+ }
59+ break ;
60+
61+ case " gists" :
62+ for (int i = 0 ; i < arr.length; i++ ) {
63+ this .gists.arr.length = arr.length;
64+ this .gists.arr[i] = arr[i][" description" ].str;
65+ }
66+ break ;
67+
68+ case " followers" :
69+ for (int i = 0 ; i < arr.length; i++ ) {
70+ this .followers.arr.length = arr.length;
71+ this .followers.arr[i] = arr[i][" login" ].str;
72+ }
73+ break ;
74+
75+ case " following" :
76+ for (int i = 0 ; i < arr.length; i++ ) {
77+ this .following.arr.length = arr.length;
78+ this .following.arr[i] = arr[i][" login" ].str;
79+ }
80+ break ;
81+
82+ default : break ;
83+ }
84+ }
85+ }
86+
87+ void main (string [] args) {
88+ auto opts = [ " repos" : false , " gists" : false , " followers" : false , " following" : false ];
89+ auto help = getopt(args,
90+ // Prevent error when passing various flags like: -rgfF
91+ config.bundling,
92+ config.caseSensitive,
93+ " r|repos" , " Shown repos" , &(opts[" repos" ]),
94+ config.caseSensitive,
95+ " g|gists" , " Shown gists" , &(opts[" gists" ]),
96+ config.caseSensitive,
97+ " f|followers" , " Shown followers" , &(opts[" followers" ]),
98+ config.caseSensitive,
99+ " F|following" , " Shown following" , &(opts[" following" ])
100+ );
101+
102+ if (help.helpWanted) {
103+ defaultGetoptPrinter(" Usage: Github <usernames...>\n\n Options:" , help.options);
104+ return ;
105+ }
106+
107+ for (int i = 1 ; i < args.length; i++ ) {
108+ auto user = new GthUser(args[i]);
109+ writeln(" Name: " , user.name);
110+ writeln(" Bio: " , user.bio);
111+ writeln(" Link: " , user.link);
112+
113+ writeln(" Public repos: " , user.repos.count);
114+ if (opts[" repos" ]) {
115+ user.fetch(" repos" );
116+
117+ foreach (idx, val; user.repos.arr)
118+ writefln(" | %03d. %s" , idx + 1 , val);
119+ }
120+
121+ writeln(" Public gists: " , user.gists.count);
122+ if (opts[" gists" ]) {
123+ user.fetch(" gists" );
124+
125+ foreach (idx, val; user.gists.arr)
126+ writefln(" | %03d. %s" , idx + 1 , val);
127+ }
128+
129+ writeln(" Followers: " , user.followers.count);
130+ if (opts[" followers" ]) {
131+ user.fetch(" followers" );
132+
133+ foreach (name; user.followers.arr)
134+ writefln(" | @%s" , name);
135+ }
136+
137+ writeln(" Following: " , user.following.count);
138+ if (opts[" following" ]) {
139+ user.fetch(" following" );
140+
141+ foreach (name; user.following.arr)
142+ writefln(" | @%s" , name);
143+ }
144+ }
145+ }
0 commit comments