C (+ sockets), 433 429 280 276 270 259 bytes
#define H"medalbot.com"
char**p,B[999],*b=B;main(f){connect(f=socket(2,1,getaddrinfo("www."H,"80",0,&p)),p[4],16);send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost:"H"\r\n\r\n",69);read(f,b,998);for(f=3;f--;puts(p))b=strchr(p=strstr(++b,"_n")+9,34),*b=0;}
Entonces resulta que C no es bueno para descargar recursos de Internet y analizarlos como JSON. ¿Quien sabe?
Este código es (naturalmente) súper laxo con verificación de errores, por lo que supongo que si medalbot.com quisiera enviar datos maliciosos, podrían desencadenar desbordamientos de búfer, etc. Además, el último código espera ciertos valores para las constantes (por ejemplo AF_INET = 2
) será probablemente ser el caso en todas partes, pero no está garantizada.
Aquí está el código original que no es tan frágil (pero aún así no es muy robusto o seguro):
#include<netdb.h>
#define H"medalbot.com"
char*b,*B,d[999];struct addrinfo*p,h;main(f){h.ai_socktype=SOCK_STREAM;getaddrinfo("www."H,"80",&h,&p);f=socket(p->ai_family,p->ai_socktype,p->ai_protocol);connect(f,p->ai_addr,p->ai_addrlen);send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost: "H":80\r\nConnection: close\r\n\r\n",92,0);recv(f,d,998,0);for(f=0,b=d;f<3;++f)B=strstr(b,"_n")+9,b=strchr(B,'}'),*strchr(B,'"')=0,puts(B);}
Descompostura:
// No imports needed whatsoever!
#define H"medalbot.com" // Re-use the host in multiple places
char**p, // This is actually a "struct addrinfo*"
B[999], // The download buffer (global to init with 0)
*b=B; // A mutable pointer to the buffer
main(f){
// Hope for the best: try the first suggested address with no fallback:
// (medalbot.com runs on Heroku which has dynamic IPs, so we must look up the
// IP each time using getaddrinfo)
f=socket(2,1,getaddrinfo("www."H,"80",0,&p));
// 2 = AF_INET
// 1 = SOCK_STREAM
// (may not match getaddrinfo, but works anyway)
// 0 = IP protocol (getaddrinfo returns 0 on success)
connect(f,p[4],16); // struct addrinfo contains a "struct sockaddr" pointer
// which is aligned at 32 bytes (4*8)
// Send the HTTP request (not quite standard, but works. 69 bytes long)
send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost:"H"\r\n\r\n",69);
// (omit flags arg in send and hope 0 will be assumed)
read(f,b,998); // Get first 998 bytes of response; same as recv(...,0)
// Loop through the top 3 & print country names:
// (p is re-used as a char* now)
for(f=3;f--;puts(p)) // Loop and print:
p=strstr(++b,"_n")+9, // Find "country_name": "
b=strchr(p,34), // Jump to closing "
*b=0; // Set the closing " to \0
}
Esto no es muy bueno para el servidor ya que no enviamos Connection: close\r\n
como parte de la solicitud HTTP. También omite el Accept
encabezado ya que medalbot.com no parece estar usando compresión en ningún caso, y pierde el espacio después Host:
(nuevamente, el servidor parece estar bien con esto). Sin embargo, no parece que se pueda eliminar nada más.
Una vez que finalizan las olimpiadas, el comportamiento más probable para este programa es segfault tratando de leer la ubicación de memoria 9. A menos que un pirata informático malvado se haga cargo del dominio, en cuyo caso el comportamiento más probable es que establezca algún byte a 0 en la dirección estructuras de información, que probablemente no sea demasiado peligroso en realidad. ¿Pero quién puede decir con estos malvados hackers?