D Paste by downs
Description: Escape home
Hide line numbers

Create new paste
Post a reply
View replies

Paste:
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  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
module geohashd;

import tools.base, tools.log, tools.downloader, std.file, std.md5: md5sum = sum;

import tools.ini, std.date, std.process: system;

static import tools.smtp;

alias std.string.toString toString;

extern(C) char* getenv(char* name);

string dateformat(int y, int m, int d) {
  return Format(y, "-", m<10?"0":"", m, "-", d<10?"0":"", d);
}

string nextDay(string s) {
  auto next = parse(s) + TicksPerSecond*60*60*24;
  return dateformat(YearFromTime(next), MonthFromTime(next)+1, DateFromTime(next)+1);
}

T strparse(T)(string s) {
  static if (is(string: T)) return s;
  else static if (is(float: T)) return s.atof();
  else static if (is(int: T)) return s.atoi();
  else static if (is(bool: T)) {
    if (s == "y") return true;
    else if (s == "n") return false;
    else throw new Exception("Invalid boolean value: "~s);
  } else static assert(false, "Don't know how to read "~T.stringof);
}

T buf_read(T)(iniFile ifile, arguments args, string name, lazy T orElse) {
  if (auto strp = name in args) {
    return strparse!(T)(*strp);
  }
  T var = ifile.get("", name, orElse);
  ifile.set("", name, var);
  return var;
}

void main(string[] a) {
  auto folder = toString(getenv("HOME".ptr)).sub(".geohash");
  if (!folder.exists()) folder.mkdir();
  auto config = new iniFile(folder.sub("geohash.cfg"));
  auto args = arguments(a);
  if ("help" in args) {
    (&writefln) /multicall
      |args.executable
      |"--home=<home address>"
      |"--maxdist=<max distance>"
      |"--area=<lat,±long>"
      |"--email=<mail>"
      |"--smtpdata=<smtp info>"
      |"--walk=y/n";
    return;
  }
  auto home = buf_read(config, args, "home", {
    writefln("Please enter your home address! ");
    return readln().chomp();
  }());
  auto maxdist = buf_read(config, args, "maxdist", {
    
    writefln("Please enter the maximal distance you are willing to travel (in km)");
    return readln().chomp().atof();
  }());
  string area = buf_read(config, args, "area", {
    writefln("Please enter your lat/long area (xx,±yy)");
    return readln().chomp();
  }());
  string email = buf_read(config, args, "email", {
    writefln("Please enter your EMail address!");
    return readln().chomp();
  }());
  bool walk = buf_read(config, args, "walk", {
    writefln("Do you want to walk there? [y/n]");
    return strparse!(bool)(readln().chomp());
  }());
  string smtpdata = buf_read(config, args, "smtpdata", {
    writefln("Please enter your SMTP server info: username:password@host. ");
    writefln("Be advised that this information will be transmitted unencrypted. ");
    writefln("When in doubt, create a temporary account. ");
    scope(exit) system("reset");
    return readln().chomp();
  }());
  /* auto dowjones = "http://ichart.finance.yahoo.com/table.csv?s=%5EDJI&a=09&b=1&c=2008&d=%25m&e=%25d&f=%25Y&g=d&ignore=.csv"
    .download().split("\n")[1].split(",");
  auto date = dowjones[0], opening = dowjones[1];*/
  auto dowjones = "http://finance.yahoo.com/d/quotes.csv?s=%5EDJI&f=od1".download()
    .split(",");
  auto opening=dowjones[0], dateinfo=dowjones[1][1 .. $-1].split("/");
  auto date = dateformat(dateinfo[2].atoi(), dateinfo[0].atoi(), dateinfo[1].atoi());
  ubyte[16] digest;
  auto lon = area.split(",")[1].atoi();
  if (lon > -30) date = nextDay(date); // 30W change
  logln("Date, including W30, ", date);
  auto infostring = Format(date, "-", opening);
  md5sum(digest, infostring);
  real toReal(ubyte[] field) {
    ulong ul;
    foreach (value; field) {
      ul = ul * 0x100 + value;
    }
    return (cast(real) ul) / ulong.max;
  }
  auto digest1 = toReal(digest[0..8]), digest2 = toReal(digest[8..16]);

  //                                          remove leading 0
  auto sp = area.split(","), dest = Format(sp[0], Format(digest1)[1 .. $], ",", sp[1], Format(digest2)[1 .. $]);
  if (home.length && (home[0] != '"' || home[$-1] != '"')) home = '"' ~ home ~ '"';
  auto groute = Format("http://maps.google.com/maps?saddr=", home, "&daddr=", dest, "&pw=2", walk?"&dirflg=w":"");
  auto grata = groute.download(); // google route data
  auto dist = grata.between("ph_dist", "about").between("x3cb\\x3e", "\\").atof();
  logln(groute, " -> ", dist, " km");
  if (dist > maxdist) { logln("Out of range!"); return; }
  logln("Within range!");
  auto host = smtpdata; string username, pass;
  auto at = host.find("@");
  if (at != -1) {
    username = host[0 .. at];
    host = host[at+1 .. $];
    auto sep = username.find(":");
    if (sep != -1) {
      pass = username[sep+1 .. $];
      username = username[0 .. sep];
    }
  }
  scope conn = new tools.smtp.Session(host);
  if (username.length) conn.auth_plain(username, pass);
  scope(exit) conn.close;
  conn.compose(email, [email], Format("[geohashd] location within range: ", dist, "km for ", date), Format(
    "A geohashing location has been discovered in your area that is close enough to reach: ", dist, "km!
The link to the Google Maps data is ", groute.htmlEscape(), " . Have fun!"
  ));
}

Replies:

    (some replies deleted)