From 9fbaa1d6cfbc3d01eeb40ac7ddbc336671f272ca Mon Sep 17 00:00:00 2001 From: Ben Busby Date: Sat, 4 Apr 2020 19:30:53 -0600 Subject: [PATCH] Added run script, updated to use config json file for general location, general restyling --- .gitignore | 3 ++- app/routes.py | 55 +++++++++++++++++++++++++--------------- app/static/css/main.css | 10 ++++---- app/static/img/logo.png | Bin 9122 -> 22782 bytes app/url.py | 4 --- run.sh | 19 ++++++++++++++ 6 files changed, 61 insertions(+), 30 deletions(-) delete mode 100644 app/url.py create mode 100755 run.sh diff --git a/.gitignore b/.gitignore index 82de859..469cf3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ venv/ +.idea/ __pycache__/ *.pyc *.pem *.xml -run.sh +config.json diff --git a/app/routes.py b/app/routes.py index 14b2d30..81c98ca 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1,40 +1,43 @@ from app import app from bs4 import BeautifulSoup from flask import request, redirect, Response, render_template +import json import os import pycurl +import rhyme import re -from .url import url_parse import urllib.parse as urlparse from urllib.parse import parse_qs from io import BytesIO -MOBILE_UA = os.environ.get('MOZ') + '/5.0 (Android 4.20; Mobile; rv:54.0) Gecko/54.0 ' + os.environ.get('FF') + '/54.0' -DESKTOP_UA = os.environ.get('MOZ') + '/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Mobile ' + os.environ.get('FF') + '/59.0' +# Get Mozilla Firefox rhyme (important) and form a new user agent +mozilla = rhyme.get_rhyme('Mo') + 'zilla' +firefox = rhyme.get_rhyme('Fire') + 'fox' +MOBILE_UA = mozilla + '/5.0 (Android 4.20; Mobile; rv:54.0) Gecko/54.0 ' + firefox + '/59.0' +DESKTOP_UA = mozilla + '/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Mobile ' + firefox + '/59.0' + +# Base search url SEARCH_URL = 'https://www.google.com/search?gbv=1&q=' +# Optional nojs tag - opens links in a contained window with all js removed +# (can be useful for achieving nojs on mobile) nojs = int(os.environ.get('NOJS')) +config = json.load(open('config.json')) + def get_ua(user_agent): return MOBILE_UA if ('Android' in user_agent or 'iPhone' in user_agent) else DESKTOP_UA -def send_request(url, ua): +def send_request(curl_url, ua): request_header = [] - # Update as an optional param - # Todo: this doesn't seem to work - ip = '64.22.92.48' - request_header.append('CLIENT-IP: ' + ip) - request_header.append('X-FORWARDED-FOR: ' + ip) - b_obj = BytesIO() crl = pycurl.Curl() - crl.setopt(crl.URL, url) + crl.setopt(crl.URL, curl_url) crl.setopt(crl.USERAGENT, ua) - crl.setopt(crl.HTTPHEADER, request_header) crl.setopt(crl.WRITEDATA, b_obj) crl.perform() crl.close() @@ -52,34 +55,44 @@ def search(): q = request.args.get('q') if q is None or len(q) <= 0: return render_template('error.html') + q = urlparse.quote(q) + # Pass along type of results (news, images, books, etc) tbm = '' if 'tbm' in request.args: tbm = '&tbm=' + request.args.get('tbm') + # Get results page start value (10 per page, ie page 2 start val = 20) start = '' if 'start' in request.args: start = '&start=' + request.args.get('start') - # Change to a config setting - near = '&near=boulder' - if 'near' in request.args: - near = '&near=' + request.args.get('near') + # Grab city from config, if available + near = '' + if 'near' in config: + near = '&near=' + config['near'] user_agent = request.headers.get('User-Agent') - full_query = url_parse(q) + tbm + start + near + full_query = q + tbm + start + near + # Aesthetic only re-skinning get_body = send_request(SEARCH_URL + full_query, get_ua(user_agent)) get_body = get_body.replace('>G<', '>Sh<') pattern = re.compile('4285f4|ea4335|fbcc05|34a853|fbbc05', re.IGNORECASE) - get_body = pattern.sub('0000ff', get_body) + get_body = pattern.sub('685e79', get_body) soup = BeautifulSoup(get_body, 'html.parser') - ad_divs = soup.find('div', {'id':'main'}).findAll('div', {'class':'ZINbbc'}, recursive=False) + # Remove all ads (TODO: Ad specific div class may change over time, look into a more generic method) + ad_divs = soup.find('div', {'id': 'main'}).findAll('div', {'class': 'ZINbbc'}, recursive=False) for div in ad_divs: div.decompose() + # Remove unnecessary button(s) + for button in soup.find_all('button'): + button.decompose() + + # Replace hrefs with only the intended destination (no "utm" type tags) for a in soup.find_all('a', href=True): href = a['href'] if 'url?q=' in href: @@ -87,8 +100,10 @@ def search(): href = parse_qs(href.query)['q'][0] if nojs: a['href'] = '/window?location=' + href - #else: + # else: # Automatically go to reader mode in ff? Not sure if possible # a['href'] = 'about:reader?url=' + href + + # Ensure no extra scripts passed through try: for script in soup("script"): script.decompose() diff --git a/app/static/css/main.css b/app/static/css/main.css index 120b572..f3472bd 100644 --- a/app/static/css/main.css +++ b/app/static/css/main.css @@ -29,26 +29,26 @@ body { #search-bar { width: 100%; - border: 3px solid #0000FF; + border: 3px solid #685e79; padding: 5px; height: 40px; border-radius: 10px; outline: none; font-size: 24px; - color: #0000FF; + color: #685e79; border-radius: 10px 10px 0 0; max-width: 600px; } #search-bar:focus{ - color: #0000FF; + color: #685e79; } #search-submit { width: 100%; height: 40px; - border: 1px solid #0000FF; - background: #0000FF; + border: 1px solid #685e79; + background: #685e79; text-align: center; color: #fff; border-radius: 10px; diff --git a/app/static/img/logo.png b/app/static/img/logo.png index 9c1701b65f3c73ca2438db937bb59167b374e134..1e9dcd0656dacf681c808a41d36e9351e1c3a892 100644 GIT binary patch literal 22782 zcmY(r1z6MF`#(Myp^}QyAtD_rIO!0O?ru<;kuo|bilEXB0s;eMq|zWT3q+(wNeRzG z4kUz8gTepc^ZEX->o+eiDcmq9knoF#gAP@+RriQ8!1OhFDKuAb0 zP=F^PfsWt64>H&Ly7wWFcS%$y56Qvr*Bv#CbRm#XJ_scGDFi|QkD^y0kbv6|$eIHL zB9je)F!{c2Gn4}_C?096t3uAs|GeoaPXkXb`lzY-gP-c)?M zEk-~#9wo3{6rru67NHcmAY#y=Fdp04*+Ut>nuh7X%wps*Jluo>tt4dJ`A5Szz;nkv zfsNerLY119lsUvj=;}ZoCIT~txrQ0zCQN80rTniU!UQz5rvFL$^NIy!HX5Omwk_t% zAb44xM>Wa^7p?mDqva6}TIF3kWUXVU^TY+m;>6~i=F{nktJsg}P6>Hevfp>}bw6L7 z6PwjPpRtVPLK%hH_|Gpb^u(W7V)~|$>y@D^@R=8wP0T*(iBi62>)M__d?o`^tBhyL zqD3b|ej6r4{1qPXiqaC%xn?lxffY1W@i7NrOg81qF>h^IqB zJCzivl&I>NHxBdPEZ0V}7e`o|`Fy3ebFlB6-m`Br%^SdH^rM-Jx$I>G{u8FmXsceh zL6x7j<-!1u>5GkwFZEsINCqTZmEWw?wD67dkCFHC2&*KG@9jFt+YfL^w`fx&TeTlQ z$??-wdjXE*|0LIbHRq_IJA$?4+D}T}0%8IrkYe*)x0jI&^M3;c_R8#9a@7A54RzmS z$=BV!Gp`Jv@rjNIK>YoF9HPxrqHw%L8W{yqd=S6l@CvejL-Z@r3Fq+NYOGRtLI0xU zGh|hUZJ#;ZLX1e;^l(c5y^O8g2TMJWo)2~S2b;g)P*0L&wGb%C@n6^9d`EM`!S9q} z5Ved=H>T`MQUk0(EiiA@|LZ)qxanL}x3*lndtscYU>&exQZIP`Z^sL=!Kiito>&UlNv7UkbB-4IW1;sdLxg?5R|R&c&2 z_eI0>wDZnYsfrq&$^^5y2RSupQ;~NQo=+-`q5mtRoYze^!IyZET_nbtn+8dQT-YYl z|Nk;QGff{p^9o~$`B5r6vJh#(;l=ZJFs#%@_K_T?MKMC1EV`u151v7*{8uba%A%ra z)t9KftlJo3wxxV2eI>WAZtLuYvIIke8JMYbD0QqmmLbdJ%Os4DO!7=9qtI+lFObe> z)@Gx)Qyli=fAYh#1fCxX=EDFStpv zww)bnurUUfEI+xVS`gR&li}?j@<19K(Ft0V_90h(a%9V@`mF27@$;!h1;w3GVoosT z$YU)!jU@;;N&hD%I^2&VK{~PSHRbabh1--tYBXW+E^4Y4rD07eMv(+A`tL4Het&{`T8xzu&n{`aS z!8pIa%1Zfl50wKHQiWQqPk$b5s)AQ^d-U(5ecWj^JyAc}G@6ns_I($uMlj6qKeemV z1Waz&r3;HA*z1(zP7{?k=(OWby&ZVxQOevu$k?qy+5c({)l4IERJ9+vX?VTc53|Wl z@OipAComM*r;M+Cz8b_Q`kBN2`qTVsKkal*%D+>=*{b9m&0Nlg`G?m+3+aZ>6#Uy8 zFASft|0D_K_aEUwa%F6G{nZ4%rs!tj+yMJ@9%h-FKqb*^T}e-L$K1nA=j8nwW|g$Z zoxVJ8sNuu<*ACKJh&kFgB5%d6o*6zeSTo}tE#&thmAU3VSo60(jlh`vqZ6&=mQEnr zu+5L(1XZIhI(%!V9JN@8_5YCgUn6abym0TdJ7rz5t19syzlo|w$%G`;WNL?tpD2!zTo4JaPRax1sy8*+6>lLPXeKv zgF^$=nATF+|IAc}>+RkZtDHwiu5qWYQezCY;!Xn`_^~-<8~cp(NT49$=d1n$?_d1w z4iclSF!Akb-$P!?;s$zRHO9~@ysrlt5q+eLmwmSCBQ~r4KiQ^LhkGRCQ62`zN^wHO zgyormA#~SY?uk9xT|mA>&OxK-hP%w$RQ|VVm3A~c>*bTEhF9bsqf&s*EEi}=PJQAO z30HhceRbka-(iXWJMKeDy(|Cb{M+&duXOhtS2UD)=J!f9%5nh6X-y*mawtxB=X-a_&hXb>V? zx(ZyBq`u*Cr(LDczb!7ayg;T7{=?YG@*+%|PI=_%YGFh7EJaoHr3>-rV`(rk3mmN~|fw1v-@lv4g@^HkR)40eucsqefZ9T$?P z|4%7Kg?u*)A!T@_|2o%*C}W?WQ_K`h+^F^gPOR{jJeXIj#ey2dpR}H&-mI1dSrJ`P zsn|oZWm4N5eYO`ylvP!1LMWmvtNbLO{@Wj6uuIvobTyTKFcu0eHFnD}@U^e>#LCj+ z>o>3!=dlbIe?;>j?GGIS_2#i%R1%&=E)(DJ>wra$B3ME7%mt?~>i%YNm)q#;G!CBV z=rK=;q0^>|(+~#zL$pb>Nef9CAOu%-?dgem z+^J&eG2ds`1nW4H$*|tFMuFRkxVIG**1_w4##>g9qVZ%4?qaMdnTEORS!3Hf~_Q`e{AsJaq{>Vusa60rNNJ5!fu1 z9>t66PU9`D8WW$FQSe9I*gLvkq~^`$AI<-uC(4&XQ#C6yy}UHqYVMIO3v-Ozl%utw zc&)3Y)=2#US>kfm6C_hWxQZbD%e+m#CAa=yZ`UmtWUe@d3?e3BNdg|0xO$i-Hl z(iM0+B;=7Fiq}EwWS~sG@LY9Gx?6hG!-^ni3prDBbu_x%+3&Wj@~St4MT#yC#lJ%k z5&FT}Oo|JgDqzea9e0p(=N%Np6gHy5R@1}BLD(QyC%nzOGw9v)?;OS*wY4X!MJXW| zqp9F}qk5^3&sb+6nnne0p25ysp&q-qdqhv1@p=_xHD8H2K=OKU76b;9NxjBDIMu^B zw57njy)dNKDf?T2F>s_JY57`P?;xwB;J{LsHa+yqJw=CmUugU73=GkT&ftn&;-C|#`AMT<&IleVWdNg~?Xf%Sgp zPX3Cb(f$i-&^?@*aF%)Wo-)2UgZXNOKA2z;eMFz;qdo2hs%=N3cW?A0Sfx@C3+246 zqVKzPFM6tnUU;XB3--Xv`QAM@?OmlYxWMriQ;msHCgv81LwP8r)HNw_)hKhY9?QKt zd>$rA&N0F%07^D(Dwztjl;yMztSP%B2HO^#i_wWONDZydHdJl3?ef z2%kwGZ}CanpF52m(3RuXeGz`SWtug}!&J})wNd5AQ|)I@dHNui`*-&j2BWWQ#OR)C zzvq?LHMFEcka@{k|0YrjMfX8UVqC<3h(kT%`mEh@KKXxme} zB@CZ&!N{YoQO)966rbQ7mPz0Xp#WF7*=e`oXO{ z7O8Z^hNrDeww`kWn{$FJX$#ZO_XxRXd%V}^tQI0Y5-N|`|I~mauZJ~=(U&COFv+2% zjGPv-S$oOh1$7?Gn-)H!iMfU<`4c)Uf~nQ4q#75!j4?nJ z&@i@GFyrCPKOUYv-m+?B5wtv1!ztwsuu8VWHm}axgt}Tz_==F(xFpEx6>6rrCgjyy zHARTHJ6qfm$Jmayz(6jP|B+QP4Yo;!%|uUX_l(@;iJsM%TQBS%TQzW1q#cyG$<-*Z zO$VRZf>8;j-F7%ns=u=ySkF7XG0zJ3BAv0xDBQ9%{fHz+!!`6toE=J{9V`F6lZ(ub zTazki*KoyrpZ~2KikX4aK`Bey$~M*dnn;!@Pc1jpxkf8!uz4V_P2*z;6ywnT+^_$= zc7O1lxVHw))77(!C-tM>Ow^JGRKhT<%_R!KPNZqN3YE_pnMmgZIozNk6gKV&>!U9^ zMS)z|ThbfK4eRq&ny*y^|5z)9y1!U^*nJ<9fe8FMY{W=W)7ZUXE0fFzn$oqr-V_oT zMGI;a&X&XH>U4A(f9$KxGn6{w=#7(`-q<=MR0cSI^?g4rA04Fq>O0vo`6;!HPr`b- zN_uHznvO!{&2`qc=C?z>;ZGWtqXw|ZMW+Po%PrS7Hay2jQRSubUDVBl_X>1}7e60+ zXE+JXUx3fJcNCadER;2M6LSzQ^_~&BW z{PTK0`$YrwK@hKYbCy%W@lD*1fqtzX?1LuW{wHGK3|&FZV$81Zew)Z$lNb> zZ;ZESSNT~PO@t|=hnq=$S}A!X9`laG*B5tv%^`v9VS?&o>Xa~@ zjdy@2f^Of1L|6KoJrb#~S_`BJ&A!9Fo2n4SD8do9Xga%||J%&3heX=0AArDpmWvgqXjPcsTtJ141#_btwa|IQ%Ui#Wu!!>t_>4>rU0W*xm^MPFOnM6!v>B6cZ)j7ZrOQdh|l7w;-@~Zs`DaB9{U9Z(i?5pi=SuYIm z^OiCJEJcXpHT8GIc#9%L*3~i{r1EyzC1Rmt3OK+ z*HsK7XgN$}67L7IwJ-#?%&ps_;46)5gA#CU<+A}&IkK5S%85}P)L>~Re9aUavvN8y%8r8L(#8t4hfgSjx%heCRK~9Mq|>@& z>yeF%aD2I*z#E|;Pxgw>RzG55)IuR#zF$X%;B*HYRi0YL&wCien5Z%ZTt2INs~1BD zbcTFJhwwY%O7Lqu%Zbc31@6GP?V_E3$|lvZop$O#t=AeEh81%QDgS);GtU%90?bAz#aK^KT>dTHiG>cOm&IN z4IEgOa)_rVmXtzSsNpl>sNFv3HuPD85Y;3e$X*o~D*a&h@(xYpvJI2dfSF$68 zRp$(k>(G-Gl^S8+a#t_TzZdGRRK^cBSIq5_uBX&g&}h=h=dKz#jG!qV^nf^v>JaOv z)6IY))i5V*h9m)9ai}S(rwshGdx;RO*7WyzYyIv#yqig|TG-^37eV(u<0ka`AHc$?z4s0sl=U*7M&VQr|Abrgn?bxHi|!%rsjXT%4RP* z&MGPEE8H(zHg9;H^p5J8Q>$^!AD~e7G zyd-(Yss_G}9%~z7-2jq4$V~{-rW_HJxqTGQawxt1oSu007-qF$I7xLI<*dS+K(3I( zT<1?elkt{kNG?cw>cE=Ela=Tt75uGqTBqv(hb4&;;!syi zf<7nVZ+09H&vq2&5xh8?C0$9O>bSJo$9T3-rV&Epo%zx9lXp4T9woFAhhw`%v_32B-hfVH{B?30ha2BM16ZcsnGq zLA|2k4(d6pZluP&)Q0qceC)eqPN4z_`<3FTHUt2!VbL+TnO)Y5@bT$EQ{;NI;H78V ztlPr#=DcYG@c^K|KNZz#@$vRP_3+u8!`b7^C5!Qvj%fQK;u3C-Vt|`h)EsuyjZUZ4 zRNx|Qq8pyGlu1?qy=qEcddYa{A1{ZG^u#Xhq_0nbhbNUZINe=(h>2aT6_V#mdz4@e zk;--XL4PKoI+spK!DYm2)|{I7LJ&uTO*<{gO-1OvWfeB>&>F0ngH%n95UVXz&w2uHDE zamC*@`Siq(n8!-Ejt_<0q7pu@(acl#pM4Id_$jB_rNY3VA5BkeL@9?Kr+SFS1%JO; zPz!C3U6u5H{O?8jVlL|?D`80UwF?jVuqq|@dz&WZRimJ|z7rH_jL|24jgk41YQG*+ zdpWGlR*Fk?Aiy~6WU}Ldd7$>BIcYGspey&|=(+>$$;KRA6@9T{o$a;F#}|eR?+YzO zhJL(VMxuwllzcZ9=IuPMPOcIRJ+z98Oly15Im)eiMqeQ?yosU|FFk2+r-Py4C&Awp zZpt!R2&qOr#QkB`h&!F7C;o$Zk7+DjNO@f4S81>uSEG&`Q^xmXamEyZbX!eE`r%N# z1Dls~!nE)0s5|h|MsOKGPaHr!{#Zgqt#ffCB{Sz2$f!K)&K};Z42s@R#sl~NO-UKQ z06=n*{aZsP*zuNYT1oc{*N_8rRI$FSbsll2omj^^?A(Mb75p^G9Hmx&RW)^ZGu{GU zk@|E&pt<(#R_w}`^Cn{}BU_rLnc5pXuPF{4O`lc??%%Xs=lwtq=HSguFxR5{Vql^k zUag(O<}UbyRgxE1q`8S6VuA_>c-$HGfPD`VtiQAv=izhgbWL!V1B7Sp34}kW`mNBf z6qwTS7I3wt`_rG--Ez={o6wa(>m;Cze{Se<(LBvXF^W>h^37}za_iY@GeCXKLg}rp z6)V0#6gXNBJZF!Msq*vB;C%i)NTXhq_qBT4KfOjxU3$Q+YxZ@C-MadT^{!K%Qh*ni z$=jpyXc!QSm^|%g)BY!sStdueeZFCR%^H12{siGV=SFN*$+OiYGLewoswL(xu0HQ1 z%FyMTz_L}f7MZX=tGe{sC!zf_>%p^F`JxTpEfRa$;jFg%9%K5Nrfuowsy!?pkSJ@tsC8S_0m5~ z<1IPbNl@I|nw(1wVZykF-5aHpZ#d9op1LlR(t;>wR?_lPl*(xvjq)r?t<5$vYAGM%8zRQv%Ie7-^ z&5!UNdnM#$nnYi3HrMQlxf?k+>T5!NZJcaVZ0N)s7?f+APhyZ)dcQy9Cd{_KlL<8y z=uH+9S=sk98qR%$hEH8}BZNA{&=X(s9?t>QTWj?BwxjLE4HfyeEL-?V<~YAwX5<%Z zDbWr7T)csL?Vb99zc4}>Uk-Vhw*Q`3i;&ByCba<&B)B?^$9}}e&CxFD6qlj*x5M*4 z^a)T!=$ou{5O)RIYeF9K zyC{8-*!RXWK|_f;}T}K->f< zl1D;P7Pyp6lC8r2*T?lctPUgIKVK?H1FTGguD5}#S(ZboQzB-ItjTM~&uqhhcif(m z^V{g+BTQKuAuB;k;rzz;;_w-@MRtQ>lnyRiJonPim+4Qv0bC-6X9b~3=b|Ab;P7&C zW$Hhy;2Mr5b$ji2%U8{nf@ORUeMEc?2D{I9 z_D8|K(#7a;U&PJv63jR^p+Mj}Lvd6#9@9D9*%y`z^Cp>x=j5_M!+{-B!$qzbaPS;H z!1~!q>%32m;7J=)Ff}ZWK^`IHzqL14HylORSNW}2EiB*S&|#Y7QJo8zFl=n*ck=M| zxPHvJH>PE? zTFA`)+2w}VndDbJvx++nLdh3dlbUBH3YLg!*1rjRE9Bi*vo^ZBOM#mJS8!88e!o^G zG#;ovK990`NQs`W)_x{!^tP7=7uwKRE-X7of4bnc57{pDw*MCfX5EY&gzCF^?z5Th z{jhmlpm-uyrwe2F>936EC+QLZ^QuAX<-@m#01DpKI%s`LPxM>tE8&xQIeWR+wGi$5 z@rawShjiAUq&xVOd&Yu1gNg|^gui8bMILyILp2{ny(HyM9%2WR*2!jyi;tO}2|M2d zq3ol1NtV2s8P;asvL=zEg7;m}@KP(n=m=h%9!UX-10eH>EZTH zrB!q@jtR$)aY`~nDW)k;yqP2#(_jE+uci^nsc3E1Sn2Y(HB7nBYfn;~g1XghWxA5Q zROK6{6lW*-Eo04d^7Yc0SJ{|KJE?KQiCBz3o3C406KkbR)^M`VQc{EEUc2S-N~H6F zcQu8)1vfz*Y47aj!O3S7TdlOINBj(9%Ped2BOo4(Pw0}Md4ST6J4pW>tH`}HDdKoiY8k78R5~jkopve!tuw~wO77|<5^x7BaWzJhje74GUVVH}(*#1R> zBEB3k_i9xc6ENO#<#|ca3v-QU!J)mpIa8J*#CnTwzX)+l1s3T zJI%xry|NV{wc|70>^i>6$`gErMAKuHD5L&3F*S5qFhhv2)VMS2ycGPkIcz3grbftn zSi6SDRH@3k21wd_b)aUysQ0GH^NAIim;Qii^EUTam^C)%djOlt=`N@2@advp2sd71{hNOU z0*vAf)hh2`SP=2zF;0)|2Gpnbgo~c*K2kYs`q_JkAK89#C1|k zh0PpXPT!gxj{WYZcJh3G`oL!AoO3WqPaNhZz%;(T*e|U=p!yAY?UK;I>8Vj^;2DK9!h>y#l-NHHLqWrl2tCo6W{5Nndh^qHxMuF(_HucRp2%p zJ?ox1+=0Y1BxW7CxoMH7FCKI?_$)nhLC{P2CI z;wa$!gX1Eljkq)HA%hu-aONfwy$Nc8WEZzk(?nvwbmnZ6{89GPv%XQiW~mIhFh$9n zpDYhWr?Ta=y^|(#3S!Lr=~tx6gZYe{`YElQ|FAUFd70*#-7vk^k+U)!;f@f8KlSugGv_-O#L0kNW-LwFn ze^lkY`uOUz*2YjHu^5wlWT$>t^l{fOwG|Q$?hM-O9^X=znP~Fv>K{^*l!xgWf}D)QD-GTZ$THJJK2; zVSm0V@9wk8)VoVQiRQ9iXcFR3&5r7L~_jQjg zn+oKxSXhQK_R`m1`b0e!&oX6EBcs@2`}jBaX;_?{M2L#NG7jQ|t@5ikIt%&dAa>RN z>bG?_Zi3|7uI2tq5is}ka9TqcTc}H1B!`3Lypw|su7&R*nQtm=Gp!UVIKP7>xr^C_ zb)6w#T~Uc_ZQ9Cs=@+jNmHrY9??TxQB9>dqevyg|0CBfP6S|DmN#P9(3Fr-y$_aS^ zj5N#Csu0NjRy%iR+k10S$D=ZPc-1fTW43SntsE{I>`bNt9D$p_fz(f>^@wOk=rG*5 zbO=wncAb@K##APb;%(TnzpAb&&vBKF|H&J+HnV)~sX2>smWs~0sp~zkfSgM-H1>_Q zH`E(918u3ajm{XK9%yK`Qs;M9w z|EASTdr2=i-5Nehk1A?+Jj(mU59Z+*cls5axRPDXo>k4=QDVCUBeQctpP^F?+bEHq z#=#vd)ohIOt$dZAI>~d$wDDQ$laEt#tU+d`Lq*fGRx;7C-wb`-t>%|le@XVx%+i3= zNxWfXW1#$W(VyH(g!N$p8;MBaLpi)sNx+KnS!?(P;nfkM-%r`c+}md?0TYFs)TX?_ zWq7bPV1gRF;+|Nl)aMNca5W$n^r84GCo&Vu#d){evG<*J9B>fU8$G{$Y$Z^-9m3!xU#4Kzi1XCOsQekj)lVjRP@sNj1(rrRjfK4<1sxOl^G2Ab!dw-Cqk z@NAej=MKC6&Hncn0GtAXX<96{s5Z@&(c?M@yaEA4Od&m99rT26^FC+QSMdfvf1F-m zymdv?oU3dNrLA%PQYN)m!$Pjbhh^p-lAv+LtF{|WSdwq*qr@pCn4NFLp&1y zoUSpGu_*8s_NOiETI9M?fD9=;+y%fWf~s8-xK~4|$3GY;0>$JxVa7W-h@BrR{2q~K zD=K*XtW77TiZILR3l77Kb0wSbOX=ZF#)+k=)piVpsM9uDX_x5s{57S!`nNbq1bV}@ z6eOsI3pJ;@5T*cj@mXjM(KS&gd97!1VD!z(WMX*+Ch4z_iww+RUy$~Bsc0Xxw`j94 zBrNk!uGMXoSIw?&C6&)s)kj`c>+c}hyJWFC{(?s$AZ-w-yX+fYM9)ap1hPt4Xgvag zO-+IZD6)sVNAS1nB>wS)8M^JQP>S=Zo@vGUtzH{UP1Jg8JW?wd%@4Fhh0mE23AkmR zwM=M99aL7vZ^f<#@#a&>bShn#6P2fcg$S$KKawkrcpNT>Q$uyga3572w_#ypYNi=j zR}b$p+{9HkHqCaoya)A*!M;5GfEU+5-$5B^@CFA1WVOuAD4M(LlSc}fMKrTRjpkrJ zdu?z3_7EA6f^SzLgD)6{^4z9Q?;9Sy!Pr{GIJNgV5+sO6dOf3gR$U(1gc{# zLo4W#o;nzNVR(!3MB2aJzNvf6wnE?OtxNAvH&vGGl4#K~#L;w0E-$1Z|kVt_;Nu#-kE_g%-cXrTLsZ)9rDZYq8C)91rGXKGED zxPHG=R&8S*P>T%~RXGcLFe@zKwEeisJ9Rl1gt;*$&l{u2gC!m7^D;J@zmZwx#50R< zO#M2Sg7Cz%nu>vRM;+_ddu3ZsP7f~0vwP5rwr+SC3m?`Htz0jQsu*~#ut@hP}dg=7={icfa@OuVvk<{C}I{msNRc392H;ALe*1HO-iZx*W z49Nn6epU3uGjXf!9k9``0DI%1sQ{RB|2x4WPp$-Ke}RKlFCGNR-3cG$ot!DF5`^mm zLPgl%ZXBbq&G#>39cR@Ui()+rgtnx|xCj4z+w@@AE|=S*utJ;i`c|Liglg`JDQ_Xo zwc;oSDPCiLbg-~)sw0JFyz((j`e+n3mXli$J|1C<%k?-P&@Ds5hpl9>ell@zbO2i_ zD}>cgyj8|7+1ODwk*05JyivYrJoNwwBlqaHmzF}Fh-#GVwo+^viS*vyws8uSd$^Xo)2aW~^lY=79|p1N@1QcPn++-U=r zBO`v~hwH9wPDMVsc9025oKJ;qH*?cT@*QB3gnw9e>2BDruQiDBV+LbO+V^jrdBk;Q ztQT+QttO3u9q5#Jz5~0R+)6gLc-#SzZ~2&VZ|*KKRo^|4-F0Ry)Tj2yZR6XEkIef4 zmy5adiSbWrD)uYGbgYS0EXMxfT+Q7T|9XY}u$O^og2RoSdVKIPyAq-3j0K9f30Phk z0l7mt!v2BKAUI<2%3({)gDX}iM{TvjU_xM_O`*CS7XINp6;b=m<{}0%kfY=%a5Qp{ zJnNeH0d#wLyoILPuL!Zy_U$vvRCYCBt_zh&G!&^8bv%BxQZITMK07gXGA<=QC8AVq*mGMI4db@Tx5w3#KJNJjy&mr1;?(TV~`?dZ875RqUTd< ztoAF13__kmU+y1IfK%s?6)dO1CXuy?(ooa~!tL|8Woljhx+sC4>g>d!D!nMdZusKF zs07O+8zB`o+kRF_4yz69-GHc`TSmm7EDF|fL*eljOJsiZY&0+5uDK)+FAAI6*4GNv zF>Xt{L6p~icrp2wUyWwZ>s(yYBhIU;CTE=2xAF?S@KGt#xeN6!_;?{H9ob^ z?u^>g>&BLC&gG|I%A=>Xf=m=VG|t)ZgBA;VH$_dQU-a@9Kq{>lOum%`)H=I4u3_`9 z;`q&ruLB;Es47uiS#Ijz6y`T@^vGR>BS7F%C(aEDTP>(LF~9UKyLR!fOS3*>^}w7n zmIWNtu_7z)Rl?5%qic&N2hEl=6dK74a~D5Sd%39<$v?h%kq)*fPw~DOFysRoUQ(yQ zyjf!-yY855k)C;cK9(a5Z|jzFrBJwEFhw`(@%7vTFKQ^5L-d4Z4UgVx4ghw$SwlC6 z_LM=?-Opz?ezpSpfthBRVm3b)&P+y8LV#A#d+n_MyK=isW`q6F_UV8$;FE20qV{p+E%)+}l zAoku=fapvL_qeVE2vn;4c8iO3bpu@cx4If&dg?WIhcp1WTztG`F2zMUsf4H>-)Y`f z!r^Tad++g&nitf7V$3n$Nv-Q;+E&Zq?d*SbKo;DFOqDxpB- z2E-}#@yVv!emznRkQ*SI6oKWPH&;NUsGq*+Ntq|8!WK|iDIjhl>Ez~EiOv7*Ywhf| z0In~)rtx;tH5H|M5t88mIREA^(w*QHS~!g~d-;&YiP51tcY4(f7`Sy19(kIyrR^B< z^zJS`yjd578wjjpxBqe`IIEd*@kBy}4Ww&~UPP}@v&5y8jSsZm*9RG6yny$we*9`y zxWT;_q>|UL(33W=l%j+hqx{{LNSu^YY7KCbW`L6f?3RM(OuPpU-$dh90rdQZ&z*4}#T zo4oK!1VsD|2$sqa{7at+1wT&Zjl*OCy-9c$rw6EmX>xtu>yd<;;_OT=ZjNU2!e9}a zRen^dt}OE%AQ_oHDUhxajFuN~9MOF&Kh*N3e=A5DH#5{0Aq&jIN7iPtI&UB+B_?n* zdEhfMz!!0?YAf6-KBd`(@I;rOcTU8m*wVVIy^}IF-+ohVIOg*+>Z}|r!?Cf0+_sBuWJzGlIzVw@Da%H^@bX6E|Mu8?~l*s(%@1xOABz8LTo z+*54HxpEkZOZ-l$MhZAh+MPtx%9Jgfi{znA?7i-i9DVn)_2@GfH&=IuV^9@CHr5)_ z>f$f}7%|}X{yfnq^VNtAZ2S5!XUhE;X4(rYIW5uIK#0I+L@;`#3&}`RI&T0Sq&If= z+qHG2;%~)mm%rNJEHlDGD}@kVsYMmf0qr7Vv-aCl;893jT|5RVg?_zZzqI(1=lJG^ zEUlw*xl0_E0~>rMH)m=MTrBqY265Wko^AL?=tYdNHY3WKWX3vC3+^b1*I>i3Amz1# z8hWez+Cer@51e$6H8E{a0+}VT=NCFpW(s8=+Q)dZOu0`yoW2ntC2cHAReY6BmG>7Ds;>Imle7m|9ZAQNe5 zs~LGs(oj#pqkaQsG>BL7-pXXI-o6eQ1Ux_Mm8O(~v@SFmQIO@BU^zekY9pX{R-&wE|*z%*nKcHAmn=LlAo!mIxv=7BmH{x5=_~||{UPgd*t(y z;Cey4Y2tE~U*XL;kzZk>XYCQ z)L9^&9tnMoYj1cg7BWd`!9B~J07-g)f8VVv_*{k2w2C}Nu4xi_l{SuF3Ngj5!fo$^ z3{%oKvg}lZ=H#xib%Ob+7F86*I=zl4z=GKd!+U@3ajH5wQ45G_Tu@1Q0Z463`}kKQ7Dg@l<%P>5)9X z<`^1}N5P&?rOiZ+LnD*lb(G0wH{6uYvN@|x>i=2ZQSAqJ@~rKRq!2Ncxxi9DPn^bR z=HyymIW)y7NZvOk`APGSdKp<0iCA;Dyj#L_Jz7luCWE$uJ~`*W%-I7ZV30|;dN=!_ zg)j<^X{`f>SKUnqZoR}sk5v1WXa%*AoYGm`a|}~=t?G=RINE1`vZI|yfLa`}eIM3* z6@C56n#9PbLK9b=Uft|}JD6V4p@xnu$2*ko5)0&>J%@BUCQKJ0p0mws#M=Kv_+f?m zhXDb|jQk?y5)UA*5 zGi%VzqsoRQEBjkmMsC8(Xf|<4c$HtN0^Q5HZZ8cqb#A@V0NY|z3!nhd>=fp;+{WF9 z4~neUcn6A+KIU>p_y*{w={9=Gt?1sxG*|nDIeXV{HyVF(eS5Fdxg$7_{pacc&VcjKrmU#|dI~OD zq73A%qD#Z}y1DmzH;%{32sN|T zfb)3?S7fre3$-VWG(^vh>5Sbc&$T0IX|r`LhXJO(A=VPhi&oz5i5#uf=LXTk4FudS|8t_zK~Y$a#@ zn=Zxg0~r3r$BaXxYEH9u+^yfA+- z+d|eXbQ&nMoq>I)v9ZrRTe;jo>T4WO6EN|vdxQE!%rVU|`^&I#OvsZno*j-8nLEbN zkE}tDntvy~>#nApp{TMIc*;=e&+tG7R7!I1n5F;T(muZhd8VDD0wRmD#%|)pL(!0f z;QiKw53W3VCUK|o4ngxBr2V&4t#I`LI6pT)8Z<|)_jdI#IEZZLV;uo8MEg_}7LoYA zoA}-u4G6FKNYkb1E7rD**CV=o3__`=dRbkOiYd)P_{)Isz`uWsf*O=L z+8dEtP3d7eOu1hr0)G0hb0YO)EVpO}% zU2>3^XVB1pt(8~UAb4m2QoPa_mP>%DiHSg!zvFdbBCvB5M}5Et$2FkQMr~9}`=x`I zYz+Fv(%X7Do7My}rZvKBwT=L6xD03@NUoH`6@kf9)BG0d3D#z6UykjKClBQy>^7ky zeA^uJjmloNbTfc4`woAdT76GCK)yn`0iR4yTt`hw@V+9WC98SYEou@f5(`KacZ@ch zf{@Dxwfi0Vqi+B$e`qmZV3+LCqfQbzj|6|+xiIGhYhXU0zO2ss9ry!9tY?abIbafz zoD?}+;L)h3I)^sID32w8A z{;UFS3~OW(SMNELJ}G(y?KHcV>;Y~QjH88_KPh7p##;&{i3Jr&AV>j~8K}VuoK_Ey z^V8K^WT!^ApAJHTEEhUm6NC-v9$KJ9*$+tBnA}boDGq(^tu}Uz?M!bVt5%$Ky9Kc6 zCxHAUkNzCX259(L*5(Y@CaclAXJcADCepW6&x~-_Ri}PG$CNyCw7AgnjrCwclLKu7 zuG!V#Gb9*!B^*)2kz}OdW|4l}>Ej(nm+Wl!=t5FZG@v!3MEwG`xr>5-Co#T8yHW?r zYf5{Zt|U^_2>v`xN8JzuGX&Ll%zy&MX1Jjr2Kk9b$YC#pk@Bvmzq&D&-O`S;J_C-h zp*vq4&1m!J*{X%Zga`IkFVD0~=)=@I}=R@K>t*j!E>B%@poFWPDiY5#^k= zK{I10a{Cpbiw}}IXUj6+)xQe675cZX)n|eo+=+kacsFp}s!@jENK(p|U%)R}K zce<^eY|*X?Uib7gxDd9Dg}sk8JuDNd@soBJMU2R6 zSP?=w-1oQaV_32^@nQF|Oq=gf9$9c`zQF_UEx`Fm9pfrmlqj^*R;W}cB+CXQ+Aqea z4(;;T)vfAxXZ~rK=nb+etF{q_Key{VpaXdJyYLw^6t501)mPmgY^F9*6g4&L%jJYl z`z(CeUI_N_JYNXYPbt+XXPgp6AL~Kb_iIKu>9QJMdG#xrEXU+2v{Mwy1Id=fW{>U} z>{v$GmqWz3uMK;onrqPcoodP0w=`|Uk1L4KdF`km$IxR?aS1skv3Y?0_wd^y`jf8K9&ZCZ?*7lVF?c+dBmY$vQdIUY zOR*48AMW%EkKdEWbw{YrSEK7@O~LO0u;>q zRyR70_d>t22FVL5w#DL)C4OHM8tdiMPE&YpPCkBPiBGqF+Q7`b34e2fRq_^YxneXY zLp(%3r3_;)!lA*{AHF>D|Fv-DflzM$A0IQ8YaL6t*=k5aTI@}h>@yh3o|5T`!nO1@ zB1VRa7G#EyB{vOaSJqtRxpkur*VN#4$=n||Mulo@qv7|N^e@kx^E~IA=kuKN`Mlq+ zt0v{X-BaSAsg{@%ogiW#gEv&q+9@R)tCdBPel;>@wmW=$NZWM3{`6cB`K!D@7nb3! z$WeVnu5#k%^mPzbyU+@kImJoYys`21;^Hz2DTP7l3AzL6zN)^ha;^}+)%(g9k}tRL zzTsF4Jo)NnxA9h=Yga=$ew(siJC zK50`TUFg15^9&>zli20gd>hYBmkvyTVA=tHthN%HE-yG0IqJ;(_~>^3*hi7Zys*t` zd5Kph3CwTE9lH`k_bahFh?frsg%(6~)wHkr!N-&L@D*QpjMP~A z45N}|7cw(^KArgmKC<+JDbxRC4iYbVoRJwE_r=T872&U_68a*Ja2WJgo>1fkJ^Ea( z)XOnHyvn~3WKc(UfPSd}GSWs{*)@X&zx+Zn#hmK;YkND9V3?N7( zt~Xe)maEFvn@WGYTDb4`jbq z?jDByG9j5AuQYbf(`(Lri~bJBEoocwb8fp>OH+3_u6O_YE%pe*lNK>Pe3JN~sS<4D zJiUB5d#0p4uaIs4Myc$G%zY5s$=t1P>)*a;(&Ac~J^v6!zAZ0!35KdWGy9VVSf?pB zhKbF_PYk+r%OE&zYVzb-CcR1}T%Kz3?`ktz5xr~7k)?f=!n*HHx@J0YI3aB_Jx8&k zJD;-aUIFL**Jk;Yy#A2LS_6@wLQ2Dp$qada zYPwuowrKLWw06_)9kc$q-hucN$Pkjoe3)s=OyBF(D4izTY4-V}QiZL?$nO-5AkGmSzZvpaD;K7%=c8B&xo;*8 zlRw?ks5aJ*^0X0wNxL|W#r37z6rPPu>T5;7kSfw!q@3t$atptIu zshV*sJI%zcm-W;`v`uPo>CYFSpKnB6jjqW2kcs1mxIs4{5EW_DOHm~zTid@d(~9UV zVKbHVL(Dgmfb_8Xsb^oEbt(YI6kSYD;C-6R;Gs)+(u3l6>+ z#&dK7-BcsTac?%+ftR{<%rUZ&&&ifplp0*WPuc3_VW!Zm6@K<^OD`LV!0~(EE@ZTB zFGu0{sgKVX% zTV^SiysyQ!%GUyIm@$o&9*jJk^K8$B>E4WKqb8mC2yP;NB!)JSG3`<)$CRwOa6HuK z(p_Z>k@AL|t=w?vspf#&Q|r#rpUFzTD}`${u62>9z;tV?xm-WRkEW$@RuT-|6`04= zA|G6=1uKuVxoa=8?+q|a;zM*;;y8X@nlhm|!8mbUqzx*FzP+m6dbRxzk11PrQg&*- zx8|rK#V{;jS=hw(YG>2(VBQX3^9nE#k%d&pOKW|gOlC$Ygt+#;wu8v%(-5U=H#DjA zF8C&8XVbRWz}dz9Z>kXnOshQ)e<_fe4Wa{dZJuju?ZH0~4+$IPitgViTS<`OFmznk z^cu9*^};0Q=2K>sKueAxHV6rNj&!1P!x@TV74r z%gHjkz_VT-Fe@KH`zJ4m!|^|*4WNdvU%CD7nq4t>6hxI&;Nf(_279c=XZ6e7p9h&% zq#Ar@P-~2zIOKHD0piPM;f;@|Bm0r#$QQPv_l>NXKLl`|s0`7cRwhr$3;Y2gAp7r> z^Bavqtzy%FOXnz;&cz`p{u=-86b&dM?R}@2zV{}ZVMo~`FF2VNMR41(%}8X_(y=@G z(pm-pXLyh+IFIAE(liOr3y>0IfTjz=;R3lTz*Pie2Z5wOp18vLZ2C+L@xt*1wO9Ty z{)z2A9zoL)L@zR=iNmjmPnQ1YDDGmTQW`21w!g!h@({{|HD2d>2 z_dB(6@85x8RBYbc%lPfpXi+(t!Qf-~Tn}GO>#v|H<05l35^S%VPZFmRZn7RHy9dW* zxt_o~3Ja^&kw>>$2MDwm2C^&$ZBhOeUMV3A2*{WP>`=!9Z8ypm?YC3Yzwe!{=E1ep zz%$!e8thw(@6-}Zn^fn6$cwDgp?g%84dWL{q~^UNM|Trfofbt4 zc4+#`uDKYvtshC*&aO4kNZ1|=X*z3G!e|v`{Pogl8M zt7h$Ooz~=dGMUXm|7@A@u!%q6pIPIPJJO@JB*|J@9j0w|?PZ5eq`f341wGw@GB;lN z*cezG_rNULhLt_;!CZJ-c1kAJygKQVvM<9(Tl2SKNpQB>qCVud{q(DYz``tE4SST- zIkNB*X?<)r_7aql&@8NB|-13 ztfl0#ldPNIgU9w`)hmL^Ft%$s=x-!)XKbitl;}9UyqkSS1KRGpoYwyiNMkai zDix`0t0HISl$fpZXJ|ak#z%J4JVn%nkfatZYAd zcdhiMX(WGp_~MtobL-z?I5%b%C<{{)NOw(&incZelojZmM7(Rn+Kd^NyQA=M?XV2; zhPk;xKW&L1X4%8A$?M6zf)QX7Z}M*NOy@=CX<=r`SIwd$;7$1jK_gUlq=!vMmGkF6 z%-9xj__m~nBv%=JL$&HMXLVMegX0X!Kg?lF+rzn*a7SvV|3eiC74i4KBraVFAuhRG z%k7VzOD2CNKbIg6b(9c@_L|YsgN;5lF)R%z1Q3bSkE!#AtyH&ARR-*9lm?d$TZwU3 z1@-3|Er>@JZ|bD<+PdJQr;l?Ubrw`jy;*pEN65&LxoH+1$a2lzS2OI6n6e{9xfv^; zX3R2LTGqulwj}C~nC#><-hnDP)eF<@JH}k-9)rsf?LycN!?Tsi|2)GUta+_C<7$O7 zI=_i-XAo5CB4hzEcg63%oKi=TaKc|^2+4Q~TtCC1Z)?{IW`85-9r~g#Y+=mx`5nUf z9V7ziWki+n&|a7oOTHFZGoHiFfGNkcPzGmuQZ^Vb_C=C zOr`Mm-onm7S&@(UF`02=xV7a-M7vl}Y8g4|j)WkkW){j0y!}wEBj~YS31^wm2X>{e zb|SaVW~`W-pfi2vbhflwEP&GBWd7`3!kr&ik$@RrR}QJPe#5DN(q=+fS2tW8{Q5wEV0p_>T+*A z2yx*3etotX+P{B9IK}2b50au@^Eq&;O06VNW%(?-07;u9T8Vh<7&}b&FuzYh3719C zFF10-49RNsBcKl}D4A}}J@wKZ?tNoW=(tBIcf#NJKI?RINXywh(y??#=^dFUh+Zkf z=bJ@Ka@@bvPp+nLZLU)Ay5++5KE);Ww1uIeV#!_H1j$I`B2sswm?~oVfYR-RFWYEr zai4mJZAh{-#y?=f#;$+;eA;8${^1eAu|M`z zha5+~`RbF0m_(QjvJ4h4US^5w%r;%P6)Q-ru*Ru zbI}}hfq}-00ehY;s42C_oL@!@pLZrS&6jxce+Bm?o9KWHK{BV;eUlFIeN4)N(T}io zK6ovT3g;wn{p`~IIkBXeW50y7Vb zRu_R|2J49y%3Nl!+XvDI$8JpuLjw~Wsb$Qs7Qu#^ZrDzxfc=i^N1@N8jX+EX!KVef zgx+76Z`FVqsxPp;N^stI5Gkky$<|4HYp3kA=JzO`3)H%>qPDLptYRVS7Ogq1=y ztOlC8&vE?>oFbC0=LEt6QwRqJx%i7hPZ0ulSSA$=6w*DR)03>mvVv^?C=8CAS5h5pw@n z2ZuU>h{QJ(=wYj;2)Jx_8v^%}TC_1H;$TCPEJg1O#usEHV=dK2b~`pUdpoK9SP)Mj z^ov+EsdlE86sf0y4G71#9sjP0LS8#O3T1&22v=KW4hPuu`KEd3h$L78@$!^X;&5N-`VN>inO_Ql_H*TUqW*EUt8HdFR! z8=G#79v&3YVPp%kr;um$hHMq9TwU}R__~$=*P;Ccqz1xylZGvh_#+vrY(QRr_dqhk z=f5Q=nuZ8(WGJ4W$q;_8-4Os|=_?3~ztd5)UxFC?@@1<=B+4lcjONuCQPZ; iYpC0;S$@oRfvxj_uAXOh`DmaGqliu(jt%zY^#2Fhmua&A literal 9122 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 diff --git a/app/url.py b/app/url.py deleted file mode 100644 index e896dcf..0000000 --- a/app/url.py +++ /dev/null @@ -1,4 +0,0 @@ - - -def url_parse(str): - return str.replace(' ', '+') diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..2878c2a --- /dev/null +++ b/run.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +# Set NOJS mode to false if unavailable +if [[ -z "$NOJS" ]]; then + export NOJS=0 +fi + +# Create config json if it doesn't exist +if [[ -f $SCRIPT_DIR/config.json ]]; then + echo "{}" > $SCRIPT_DIR/config.json +fi + +pkill flask + +# TODO: Set up the following for running over https +#--cert=./app/cert.pem --key=./app/key.pem +$SCRIPT_DIR/venv/bin/flask run