# HG changeset patch # User Dennis Fink # Date 2015-06-15 20:24:13 # Node ID f60824dd1290585ebf56d3ffbb17bb50666339e4 # Parent 1ad4e1acab67a5dac1bbb57e8207a01488f77c6c Added inital version diff --git a/spaceapi/__init__.py b/spaceapi/__init__.py new file mode 100644 --- /dev/null +++ b/spaceapi/__init__.py @@ -0,0 +1,109 @@ +import json +import os +import os.path +import calendar +import base64 +import copy + +from datetime import datetime + +from flask import Flask, jsonify, request, render_template +from flask.ext.httpauth import HTTPDigestAuth + +config_file = os.path.abspath('config.json') +default_json_file = os.path.abspath('default.json') +last_state_file = os.path.abspath('laststate.json') + +default_json = json.load(open(default_json_file, encoding='utf-8')) + +if os.path.exists(last_state_file): + with open(last_state_file, encoding='utf-8') as f: + active_json = json.load(f) + + if os.path.getmtime(last_state_file) < os.path.getmtime(default_json_file): + backup = copy.deepcopy(active_json) + active_json.update(default_json) + active_json['state']['open'] = backup['state']['open'] + active_json['state']['lastchange'] = backup['state']['lastchange'] +else: + active_json = copy.deepcopy(default_json) + +app = Flask(__name__) +auth = HTTPDigestAuth() + +_default_secret_key = base64.b64encode(os.urandom(32)).decode('utf-8') +app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', _default_secret_key) + +if not hasattr(app.config, 'from_json'): + def from_json(file, silent=True): + try: + with open(file, encoding='utf-8') as json_file: + obj = json.load(json_file) + except IOError: + if silent: + return False + raise + + for key in obj: + if key.isupper(): + app.config[key] = obj[key] + + return True + + app.config.from_json = from_json + +app.config.from_json(config_file, silent=True) + + +@auth.get_password +def get_pw(username): + if username == app.config.get('HTTP_DIGEST_AUTH_USER'): + return app.config.get('HTTP_DIGEST_AUTH_PASSWORD') + return None + + +def request_wants_json(): + best = request.accept_mimetypes.best_match( + ['application/json', 'text/html'] + ) + return best == 'application/json' and \ + request.accept_mimetypes[best] > \ + request.accept_mimetypes['text/html'] + + +def save_last_state(): + + with open(last_state_file, mode='w', encoding='utf-8') as f: + json.dump(active_json, f, sort_keys=True) + + +@app.route('/') +def index(): + if request_wants_json(): + return jsonify(active_json) + return render_template('index.html', status=active_json) + + +@app.route('/status.json') +def status_json(): + return jsonify(active_json) + + +@app.route('/set_state/', methods=('PUT',)) +@auth.login_required +def set_state(state): + + if state == 'open': + active_json['state']['open'] = True + elif state == 'close': + active_json['state']['open'] = False + else: + return 400 + + active_json['state']['lastchange'] = calendar.timegm( + datetime.now().timetuple() + ) + + save_last_state() + + return jsonify(active_json) diff --git a/spaceapi/static/closed.png b/spaceapi/static/closed.png new file mode 100644 index 0000000000000000000000000000000000000000..35e5252646845179a690aed9c4743dcda19cd125 GIT binary patch literal 5343 zc$@*>6d>z~P)8O# z8swk?qr8ztaWafBgo6uPB0GaDF={02Bm;>E2_3d1gwW}wYW}$2mwNf7s=KPXs=KLmz*Jx~&=l|M;T&KE@EUN7hmk{q?7y)C z(5}}XcaYQT$v_vd8L(6u+okU^-URytz0Uz(06sk=$o?Du2@C_)0=N47v7Hn&5csi! zwUJp(CC($oARYZK$Vl_<({n4(CbPO7a7?uM(gHuRnI7SH9tIv7Y=X?x(Xq7Yc>*xn z+p(PvOpLY}6@w!O>plEhAGHhY9P9GG75r$kw6()Qc1R;@J9dsVY;RyZ@cl^B0Je!V zdA*0<3J7IomKQmA-{(zn(D+;<3$fk=d3N;rLM-G+`n}0P%RJl$d@kB11-w-N6(1sP z?ecKJkZG+==#d6C2W|n5j?{m@i$#F*X`g9LB0c#pfJ2QPK zurP9N;|tytG_3&YOunB6ECX7Kd_O$;&t~AG3P-|t+`+0L(^~o178nZ*O9(ON;631~ zZZs+$TL5EWyi*pU zQY+D^^SJ`}w}g+K3M?vM)`tXHt}roe==2s^EReu*5o=S;(G~sfT3{ETHA%D&`N+!H zn=WrY@-M*Q5zy(-qZUH!5-M(Z?lo10R;A@r!#-JQRJK%;6`|MR@{^PL;2a+Wj(4!i z!=6IDYZ}eOrpwT(tY&v6ngqErgqYHA>@R;csgKTa9RzeXX^;L*qscX^8eFJx27tW@xkmBwxtg7!Wd z;drlha6u!-k)>$l7zweXNHE^r$VQJH3QU4ZCPt+(W}k&y{V|%lLzoV-N5UM%Vd)Ak zL`wgWDPT@J_1(V$f5Hl;wkG0Bt7LIHf$2wDQPu(v>A8c@v`)fkv|$x!V<}pa0nT)A zlZV}b?_eZ%wKX;5Bu{m4>!3re9?l1@si6tX^|86_1om_A=SBlPJt4<^YwTMBitUsS z&erh1aI6q(g-rXhaRRrC`l|J*!~!f)OxZRVG%|-};!h?Y+@~1W zRor3XP67VtEl)alm>qA~ihZzn@)l`oOM)PXk!WgwXy)I5a~#|gkssNCSO(G)*a@ko z{eUSBZkE}-8#pQw;!@xpEP>pY%uR1mY&gIBfeW4GNAZTzH^jjML9k_Mj?Zh`9N_c1 z2-i4Or+JGve+BF|Kr}KYF4CAFuf=L*S78Z(?10zE1o%mTWkEdr9IH%bo++?RoOvCK(lgfE&RqNEe6KU(adEf6Y&NS5fD zQmqiEB46fBu4%) zZfk^yuM^3UQB_2O~tHl0{Ye+o5+xBF)Xmc+q%s!dDFsz!@*My zzK$i`Uje@1ExF!`t;(JZd{!~+ld=k5l@L?p7bI1#ksdw)+yI>D;Fa#wy%bX*^m(*c;h!6!1IXENppvtAp)4 zT!LkM7CWs*^M-t%bhb~$f*gUdI6DC|9Xt|M2?W3QX>5tw{;LJJ?!LpHM zx*w}hzsqT5mw?IvGKaeg^lXnU|Lbn71AZhn>~8G3%>+)BrXP*f4?Qa3e?qACF`?(9 z+{PB7bkiyld7;eB{ocw5yVP+b9QZZBLni&p)AIH3>xQv+r7=I%N%^*4NmWg6*N7qnL0l)8FJnh+sp^H93WI>mOM`k zwq|52`N`9wNs405mjzT_6ezk+WI!j;f?99O=6{Xx)Bp!c;46WTdh?^VU`49&gGAhBDDVNLl`y{3^1aVJX5>q@iB_{|az~LZJ7=DD4|2Sx+dokRYc?o3i9* zM5+i!8Q#CIS+=bl{y-e>D#p9ZnWr75}tsYw`j%?AR7#;bvd}>Sd*-Wf( z`XL9O@n&8p00%pG%-eN+8`#kqTU3#0otp5Sscr-x-j9|52Xe-J3*b&~Ybwta)wW?Z zbcxmU%@XoQutm0)iXF-&CjLZe|1@tC<{ly1(D!xtWG=VVqb1Vf4s1eP417bs8DFDwFsA2A z65f0Xa&qLe!3xEW0q#(2pDPxdr^G~Dtsk5yAd{kgGZ%dUeABA=d&w6^IH|hHDfGKH1YOT&0*NtnTfp^f441=NeRyIf0Q>=KjD($^BzT=F0CZL;MjEF_ArMqA0?8#z zf2ss+4A)~fg<9KazYnk~h~+})%bWqEq@Ua@@xR5;d)%V!gh+{kk6bM*YW92A*(mP*0R-5adWK8@`QZ%D5ui-{j!TM5a4~Rf*5V(mVB# zNd6G(n)LuiwT+iA`brtr0v~rWs}|j(C(t-4#ViaFxE?O3$S9g2c?PM#i}pH zO7jm@Jh~_Fda=w@2tV2!?Cvc%JwCxd#^c#Slfl6v57%M&$5Ll~EysEh6`_ptH3v_4 z^Jf>AAj~YL1y5p)etToyUjoiAHW_3MCu!oH6@7J|g!&@za|g@1E2vJzW!6RxVKwg!U4( zafT4+aGBJ%L^`a~bsr@QI9V}l7|&syNm_uPh~=5;EDS0w_DkAf+4@nk{qJ^j&_9%r z>jm@#Aw1yVu!Ji}1NVv!>!h@*`451zoaG~j1MMZG@W#qqPAl=4|ALY4Phh=kkJ7aa zdD4lROa*;qGW(I-piQ%Al`p=$V6tF$J&^+8ybkrYWG|-2nw(K&vnhS)!*Hy{_N~C? zC6;8Ybw-v?lbL@^@#5PUCHE%@>@;AcGe)gLQNagY{l5P$}fCmifC7q1`PArg6SpBMy;KRTb z4%)qOqBF5n(%1+rh5ge7V(AoCx-kc4or6@ z+;Co>!x|4BUgG(LV1E{tv&|;1&r*@+>1bl6yP5QJffJPb{RP%R8myQ5`Q62mz0t^1 zft$+!4CMyx%Ybu3xr2~#I?{~JVvQXX7f-t-|+B#b2yH+T@RerA(tFwu3SS109&4{%uXBwg?wYFojX*cx`R_z-seqe)z*9n`5&su zlqApJ1)g`7gboD4EwTt}vDD!7?&_m@E65oNSep`{qC@f0gkGHcLSROtHpuPfnjVE! zTC_w~=|~6jN~u_^)Fkebu=6W`zjqclAqHh!nLwpe;m*m8Dnz-52@#muOyS7|dJaJ5 z4Qzqbyi(VOWXe2{Ff+D~OyP3b@V8_JM^u1dgP*;?!OPWJ*ivUgOk-L9`SP{v*tF0& zi`4;VfXlooMmr_2N#**ol>Eq+k!e0P)PM>aPp15&YzBD7!Hrto)o{0UaK?@;m;bv> zAf{EWS;b$+V=&q?KSlI4z(z(Qv%$%fgc8Mk8vzcRMk?3ylmV4Rf$HgRv=0Nx)ksd|z0uUF`RkMYoM8NC!3$YQ-Dv_5+0=@wvsJ+H2%% zrVi5T=D=_FKKzKd#MwoVWe7ilU|+y0!?wiw3B;8LA?Tfx2yGhCoQ6!%$ry*)F3Ru< ztO8+r#Ejvrj`lT-CQJiAQ%E*j!pyL7(Q`+pLi128Jm`uJXsuA!LUEtT3`uzZ%K!u# z6{$*yUl9Ek*36vi;HTce&U7~AQr}5v>o2@5pgrE%s^_XOJH^aon+{--IK+iwGrF*P zpSWX26R^s`>v3n0MntO0H{KylOaq5FBhvvsDNB{S$?2MC!oPu${CiPLB4RiadJ|T10S$UzMtK(VVGEOA!qaVD0Q+Y_s}n1S&klF6@Oa3?HHmfSg(3Lo( zvl8g`Z&)HVu43Op`=qO^mHo;P38jvSwCXZ_-WCD930T`Sfa|s9CQSUj$k)35IEm_A zf#r4S8k|Hifh@(?f1;VRQ{sKKj-ejFQ|OSngs9JgOlt?$^$OrlmuGQ;Vuij1_c&>3B1EwKYJ{yDiyZx|aGFT;mmk>V$zU-|3Tx%uBJJpXfI0VO6Vw~Z5J%ldSI+QdGEj&q~qD0ECk z&g)o=KyMcXx2l?{yN10nW*vf{>x5VzmU(TjrvFb5UFw>Tpe&({=ew9DRuu~j39@#Y zm|XV~%0z3@HEc+bwF|R?|H~y}_U2k#_sq~GubD=U!TQ+7>mk7s$r-AQ(1$d#c4I{1 zeW+R5Mc<`{1UWEF>&ip|_&0jqTK=-Cw+2qfPT5!3qqR^qxG#JMf^<*Y^yWXy-OuNH z@l|{rJrDySS&+f{0)%mut8yolR5FnF8?U6w#sPU0EN8o6GZi1cT&avKQYlZ9IM~7p;W=^6Zakn0H;W+mT(t&uobC~A3JHVk)mM}*RU5$Y+%$fkq{|7K9jmJ^<8EOCk002ovPDHLkV1n6NHk$wd diff --git a/spaceapi/static/open.png b/spaceapi/static/open.png new file mode 100644 index 0000000000000000000000000000000000000000..25aa564071036d74b9667dca017daeac563fc2f8 GIT binary patch literal 5573 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 TU|oM^00000NkvXXu0mjfk#NIq diff --git a/spaceapi/templates/index.html b/spaceapi/templates/index.html new file mode 100644 --- /dev/null +++ b/spaceapi/templates/index.html @@ -0,0 +1,11 @@ + + + {% if status['state']['open'] %} + +

Yes, we're open!

+ {% else %} + +

Sorry, we're closed!

+ {% endif %} + +