proxy.d (2990B)
1 import std.socket; 2 import std.stdio; 3 import std.conv:to; 4 import std.typecons; 5 import std.experimental.logger; 6 import std.range; 7 import bastlibridge.http; 8 import bastlibridge.telegram; 9 10 auto telegram=Nullable!Telegram.init; 11 ubyte[] buf=new ubyte[1024]; 12 13 immutable string index=` 14 ____ ___ _____________ ____ 15 / __ )/ | / ___/_ __/ / / _/ 16 / __ / /| | \__ \ / / / / / / 17 / /_/ / ___ |___/ // / / /____/ / 18 /_____/_/ |_/____//_/ /_____/___/ 19 `c; 20 21 immutable string fof=` 22 _ _ ___ _ _ 23 | || | / _ \| || | 24 | || |_| | | | || |_ 25 |__ _| |_| |__ _| 26 |_| \___/ |_| 27 `c; 28 29 immutable string teapot=r" 30 _ 31 _,(_)._ 32 ___,(_______). 33 ,'__. \ /\_ 34 /,' / \ / / 35 | | | |,' / 36 \`.| / 37 `. : : / 38 `. :.,' 39 `-.________,-' 40 "c; 41 42 void bridge(Socket ins, Socket outs, ubyte[] buf){ 43 trace("Bridging between sockets"); 44 size_t total=0; 45 size_t ret=0; 46 do{ 47 ret=ins.receive(buf); 48 total+=ret; 49 outs.send(buf[0..ret]); 50 }while(ret==buf.length); 51 trace("Bridged a total of ", total, " bytes"); 52 } 53 54 void handleClient(Socket newsock){ 55 scope(exit){ 56 newsock.close(); 57 } 58 trace("Handling client "~newsock.remoteAddress.to!string); 59 static HttpResponse!void res; 60 auto req=receiveHttpRequest(newsock, buf); 61 if(req.isNull){ 62 info("Socket gone"); 63 return; 64 } 65 writeln(req); 66 void not_found(){ 67 res.response(404, "Not Found"); 68 res.header("Connection","close"); 69 res.header("Content-Type","text/plain"); 70 res.data(fof); 71 res.perform(newsock); 72 } 73 if(req.url=="/"){ 74 res.response(200, "OK"); 75 res.header("Content-Type","text/plain"); 76 res.header("Connection","close"); 77 res.data(index); 78 res.perform(newsock); 79 } 80 else if(req.url[1]!='?'){ 81 not_found(); 82 } 83 else{ 84 JSONValue file; 85 try{ 86 file=telegram.getFile(req.url[2..$]); 87 } 88 catch(TelegramException e){ 89 not_found(); 90 return; 91 } 92 catch(Exception e){ 93 res.response(418, "I'm a teapot"); 94 res.header("Connection", "close"); 95 res.header("Content-Type", "text/plain"); 96 res.data(teapot); 97 res.perform(newsock); 98 return; 99 } 100 string path=file["file_path"].str; 101 static HttpRequest!void r2; 102 r2.request("GET", chain("file/bot", telegram.token, "/", path)); 103 r2.header("Host", telegram.ApiAddr); 104 r2.header("Connection", "close"); 105 r2.perform(telegram.sock); 106 ubyte[1024] buffer; 107 bridge(telegram.sock, newsock, buffer); 108 } 109 } 110 111 void main(string[] args){ 112 if(args.length!=4){ 113 stderr.writeln("Usage: ", args[0], " <TELEGRAM_TOKEN> <IP> <PORT>"); 114 } 115 116 Address addr=parseAddress(args[2], args[3].to!ushort); 117 telegram=Telegram(args[1]); 118 telegram.connect(); 119 scope(exit){ 120 telegram.disconnect(); 121 } 122 info("Listening on "~addr.toString); 123 124 Socket server=new TcpSocket(); 125 info("Binding to Address"); 126 server.bind(addr); 127 scope(exit){ 128 server.close(); 129 } 130 info("Listening"); 131 server.listen(10); 132 while(true){ 133 auto newsock=server.accept(); 134 handleClient(newsock); 135 } 136 }