From e0fcf537881005b018162e6e01bd3fc31be82e36 Mon Sep 17 00:00:00 2001 From: retoor Date: Tue, 26 Nov 2024 06:24:14 +0100 Subject: [PATCH] Update storage quota. --- README.md | 5 +- dist/rupload-1.3.37-py3-none-any.whl | Bin 5267 -> 0 bytes dist/rupload-1.3.37.tar.gz | Bin 4561 -> 0 bytes src/rupload.egg-info/PKG-INFO | 5 +- src/rupload/__pycache__/app.cpython-312.pyc | Bin 11020 -> 12183 bytes src/rupload/__pycache__/cli.cpython-312.pyc | Bin 1855 -> 2085 bytes src/rupload/app.py | 92 ++++++++++++++++---- src/rupload/cli.py | 15 +++- 8 files changed, 90 insertions(+), 27 deletions(-) delete mode 100644 dist/rupload-1.3.37-py3-none-any.whl delete mode 100644 dist/rupload-1.3.37.tar.gz diff --git a/README.md b/README.md index 9d7deec..c1f0950 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ # RUpload -## About -Easiest way to upload files to a server. +Easiest file manager for your server made for public use. -Since it doesn't have captcha or whatsoever, it's only usable with people you trust on a not listed domain. It's destined for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, so it would never go terribly wrong. +It doesn't have captcha or whatsoever. It's designed for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, that's it's only security. Rate limiting is in consideration. The default file size is 50Mb. The default storage quota for whole directory is 10Gb. Default config will prevent your server for heavy abuse. ## Installation ``` diff --git a/dist/rupload-1.3.37-py3-none-any.whl b/dist/rupload-1.3.37-py3-none-any.whl deleted file mode 100644 index e3a2f48ea492974d5c6eecdf397124a8dfb6907a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5267 zcma)=cUV)|*2Y8c1f+`6dnbT^0s>0tRcWCbX(AAiCMBUskuF7$s`O?Iy@T}LOXz|E zQltiyBH+cDZ>}@UeDmCsXP=z&$NH`HoOAZO-@SCyad4>t001GNipLvraRI>odAc~L zE{2P{vx5`VO4!1}4rb?OVIkz~g#*y}A443WcCdd8`Is`rB1!}RC@}#5JQQMIf^!L}z*%}X!;0DL2^8t47#B2Bl(}~Hb*Q&WtoT$rY($fT zc;n+5P<<5-VhO0vzm#c!yAyaY>n?W|!#y?7_OT?D=00)xdy({~?q<2_g+=}uujnvA z9wG@)e=<_}tFuVUSWG4L`~BQ*edjuh%gQ1WqqMtFm{0XnwUs?{G`ZJe94E8#qsaqHiCx zObk2lRW&zcu~OpbTQS9`wWF@jk&!r6>FchJ$Ow#P8OPb~;hmlhfFptg?&EKMO4uUTo}4$nZyw!jWXp(40pUu7jElvz2&Oa+nI2;Po7~5v+G* zXVqQmjNo4%KUju+09XiI7wtnYyE(wzyJO2EG6j~ZkMnejx;qo>=3RV!Zwqa2KCh95 z`Dvx$=cHi)c;auqD_+Mj(L`~r*iPnFBQYAS--gk6tO^v#FFmfupAApQ2r2z|MZPF3|i{B zw`C(kcp9nRQw49%fov7=bS2g~ZkgXZ&Mw(s%F^*Mp2Z%DA)ZsmMK&i1TSSxSsir%+ zaE%7^-!>tGaG5$#-5}9fp8iTp z!mL)2NDrV&iFdFu{~pEr(d*HuszJV5!rOb?DiSfT9^wS>rz4)fM5Nqlm5C@o6dn25 zce{-EH>i?^n4?oQc)X_#$nhWXq9#f@Q^V5^+L$xV8(8_3;=;SI5Fvq_jT)YKzE(+! zG&+bq1nv?pOh)KN5dp8Ikm&Amf{2Ll$M#L?oaayu4i1#yAp!B*xN@bZ5Aq6EuGs84 z!13$XB?Cjm?A9iYMj10Sr}mBM)Mxt8OWa}Tc(E663xCL$bo96X@b9r`%WCk$tNpwg z*sxl}Qv@;?VDGOWr_eE)EH#?dDw*k8w^5@TX8MrQYuc_jImI7H<70s|G@a1bdU)c$ zsEomxV9BV%T|U;msJYF0Byw*o}tNPrR8z^IVsbuqy!ZzLmNUcg!UR&h#cji%bmG zrwVo5#MZU)*WFDVNuj8FvxJ6)77CVvYB3qZyvHHUz&RfV=IX!?9_q`ISYhwY!yIP0 zVqx0(iUv@5<`?I&cXsd?*V_D7*c(s1{S0o{b^#G=VzA-)nyp}_7WX@$&u_04W^4vV zw}18L9F%%9AI4xW%xv1KTuvuDWmnSmBAnNWSdKvik=6=ZKFLjzOkRtpLj=V&$Kfyy z=#p&rnHF&})iy{DMY%SI>aah1xfx9aW>9=zOw=I3<;egsQdwSwPqsp*u`6;zbW>Yz zWLCxFE+QJK1i7QjNlRKBEDqvz6wbCf4k`oD4SK_Bi?mLgY(T-2Z0&rH(~qP#%EKQ> zjv6PvU#=#t&m{i>kn5Z73@8(DAxfp`*A#pff#)_y45!?Dq9_!N9Efwl5PJ6AMx>m) z&Rl8cMp;{e>|7$uufe%<;ygZ=BFDPK8Wkw4q#O_1br?%`b|xncol0o}R?ZRkALDm# z6_L8g@zuA86WNEas^L%S57;Utxj)GcrOlVdf^BRHuyA@Gz;H^tIKmFc zY<%deouz|uW&P94h#OjS2A%4@IwUd~SD^t;b;H3BQYnvYG$%s5@serCDo_n&<5VUWLQN7Nl!+o6=RVyf1~zd ztCo~mxn*Se^eR(U#F>a7OCGtx7a5vts`6EQ`yS;2+!*qn>k;d^iVZUl-C`?Hx zEmd)0Ub*iBql!=uL^|%_#s`8)&v{i~h0MTc03&oxPr!lUz}HZOa1#GkvUy*| ztzg`$CBd5kUu7t$q_W>B9zv**#aSVmUEiORkEjDDs>S-<^3wHbuLPtsYAJ)#S&3~# zDLqtFb-#S~aVKxc;f%R8IcKY#^&6L{i)NSE%+*en~Ls)jxafq_LjKvcEnR+8NjGzsb^9NZGV7Yn1kN}{Wu!IRUAy@)#alr_@H zHv&z0Ci}HJGWU9#6sRIGceXe+%k2=|LRKZK{xsS#Jiz$=o7X&dKgH~wL~Eqon-*Jj z^r|QV_{%!G`%2rnh2RaJ6aqtu8CG=sKYVBA=JLf53pO3WvHkGph3r9;H`TF$LT>=x_br?n7!&I+7DRg6nk zC+n9Wy)jR(X0pj%{;ByFWgT#vRaxi1>IaraFd{uWo2%%%Zq^|vV-f-FMs5xftMKXAGvVww)g-5 z>o0392oe$#5|b3NvU7D4w1e3=32TD&6ciQo6r%JTwP!^r&bKX|Tww-;1tmScTQqJr zZ>*S0t7DR9_lOVXLSY}BK23M$_^UK`ZnF}-?nHajYKG4?e3d9pgR^Jt+AY-E^;TUt z&!APbnX`2!Qlq2OjsEGU!O~YRy@ckANTL|KjRj9Qt|M7OO^M(=7kYV@+3f996gy(W{gWj~{r~g37?f@#-l3jn7js$d{OF;*>5bRV%Bd&N{6@ijl9Y3VQ-@RyX6A3Gp;3(I7w$hVQn;5h_16XBuTWvr)?QrJI)7{n8R6D zFmWYG_&9^3hkP`UrGYf5NG?x&=OpjHt`7qDnT-Dk4oKtrI$7su{*Ww}}{LE?*O z43<=WVw&=bl$EI=%t}TTX@BJj0wEZFA}&p_;vD*!{L`-Rr?cG|3%>FNKwzT|-k0Jt z)_3VROSwta^akqdVx`+%HA1qc;Aw3vl&qm{0z^9`m0oMecE9}GYKmO&EqjgB>%m!8 z&AE=K30_-2FVO8BAT9UmQj7D6MgHiza!lWP4P!>%cQDTh8#N=>*-k|Kh-b~KDBltf z5PJ__TML??9M+`?obgtICrxKN0HyrKJN5y$%W3NQft8%f7KY#SL8mJ5*dO?b;XlxE zSgrAw+wCZ0ldr>axZ>DkZF0PEL>VbV<%PnC`Z0Jjbr|fr zfZ+t&IiBq5n((#?Ho5B>O`8&Jrv$&m@aKGZjTPr?dNB`7F2==f^N$Vf-{*s&3K*<` z*8(DL6CuSLHp?HLA{8ad6gX%w@E+ZUFh$+8If`)JVVj%uXTM)j*t<$s7LH# z@cvs})-X30FAHZUJD8iRkejDlgx25?|KN~nl(3diuK*8k^a>xJV0VwU#t6TbAfLK^ ziN60{ysIeEg-UF{=1*JopAW;EWxtU4A{pVu;QF_uZcfe?4%Qyl4nH&U|IYu2eTjx! zXI&h6vCbeb_JC%=}dJRsbkq zZ@pU7e#zjwT=N2%<3!H1^qm|oQr67$+9nlF{qMPJhK*^@T~LFL zd$nWZ(E%%6%VNmfC*=3AM`{~CC~_UYy8*7n=-P48xRr2JcgT3&>)#%mX$_`ohgiB> ziqiD4VW+(-_DgjIXQbTPyzVu&1C#bL)w#2wS{hnR?Jv`#tf9wl*u7U~xXrMr_@wYQ zgE_U80y;SIAd>s*)BPqqe3jj}#~ z9nOkM>Bc9aRz2~WSF>f)?l|`~xq~s^o*_X`P7UE@rc}k@iu8a z8K}EjNmd9EF1hyom_L26S5@0;Y5UbAEL`IJM!ixfnQABHAVFon;t-omo%4pAFS??j zmHl0YE3x`iTBGn&J^TIJ9lakCG2`!W+^KIE*o#lqQYdIVYP*VZBHWa9liJ<_>ZoI3 zQ{(*q9iNLA`P-2b@bm8<`al0W;ODpf3-I4=&}G2oZqRS(FHSiDHh%*A-W$3cd)e#! zifzB>Fa44Hcjxox*ne6of5oYtO9>9D*^;4{-xC4H9b?Acw9k4llCgodvrA=?_C{P(#4_y8$VvD;MHt%0-_NdWia z0=O^m0yGB3;O}Sl?T^@Yaq{GMNv23`zot1Jm)Gq1&>RhiPtfg?1Eft#?F7(2d7No9 zLjffLwuZCuX!_UL^x4c9k7qM;q&-pTkDroF>_@iS9~xt0JRAIO{6Cvc+xZ`^hm+Z8 zIGT>9Baj8dkvW_`LDNI>e-cG>Z%2J1|Nm(+l>ArnU&((Z|AqWN`^OLcS3kXc``P*b zXfkQz|1rq^n*1LRhqEWhJS6`=Qu+S|Q`@zv-TzOVq$CRGXk-kvpX>n7Q8qWUB1=pX z?cF8_>|{GfA|KHx^0m_qT}R0ronyF7vfDlmY~lkX{_yWXCM>Hz zCn=pHn?!3$V+&vmP57^#&*)7twXC6WWQ;WJDLQ{IDAk@mMW@SXL$w!nN^nZijlBi> za!NholkD8^9?*V|}=XaW-wN&tp1qR58^V;4X}KZXW+#j3l|E)v314}iy; zrB57yhI`0PkspOCMAta0fe3F=28D#Y-FD)v5e`=XgF%G$rtsV+0iibQY7UoCic<0~ z0GmdPx|?X@yC`I2pj89|kR)UYblfC>(%?P!Dg<8geGWwX`RAXtn2+Wd^#gQ`!)s)) zznU>%KZ7L+2ciJWk4X&eI1iQ+tKk-O^6iS~edI-u39RzrNB?Q@ZT;*HKDC zn8fJEx9=`~I(_q^y=WXI6rH_2zi2Na@GiW_2O9~!KYRW5^!eiD+t<%uoPV;?Ch_wc z@6TVi7Z2>)1?%($>vZ(y^uHD_U%h^@c=zgmpzYc_5K@#6EFYL`Iu>&<;yjYh0eXMk zLqI?FV;MoZj&7hjNfFNpaLRiYwIn-q5xymq!Q1UiC~yHSDW0?W0!?d$mN%0DD|%bX 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 diff --git a/src/rupload.egg-info/PKG-INFO b/src/rupload.egg-info/PKG-INFO index 25df069..46c324a 100644 --- a/src/rupload.egg-info/PKG-INFO +++ b/src/rupload.egg-info/PKG-INFO @@ -12,10 +12,9 @@ Requires-Dist: dataset==1.6.2 # RUpload -## About -Easiest way to upload files to a server. +Easiest file manager for your server made for public use. -Since it doesn't have captcha or whatsoever, it's only usable with people you trust on a not listed domain. It's destined for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, so it would never go terribly wrong. +It doesn't have captcha or whatsoever. It's designed for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, that's it's only security. Rate limiting is in consideration. The default file size is 50Mb. The default storage quota for whole directory is 10Gb. Default config will prevent your server for heavy abuse. ## Installation ``` diff --git a/src/rupload/__pycache__/app.cpython-312.pyc b/src/rupload/__pycache__/app.cpython-312.pyc index 42295ff1091694883318ded62381af49238aad6b..3a25dad331b960feef140a0ac6934e3bfd4a0fbf 100644 GIT binary patch delta 4357 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 delta 3376 zcmZ`5ZERG>arfSP_w761o$=XcpYgZ-@E7Kzq+m>H^O4%%AdFIC1J~o;GqyR~*L}|c z%sIXg+Sn2axZBo;S_F}*ga}ehX;su;sYE11RrN0C)b6WWMXHpxKhhc-scG7(oqfKu z4YcoWXJ=<;XJ=<;W@jpJ@ujL?W@T9se1^k&PVOy2=#OlW`AlhK>EUG6Psb#;cJ9!A*)LmM`v)Cu@i|#&2(ru5*`XlniYCFfy>51{2J*T;H)j}2k>1yg`$Qi z3al_hIT+#0Fp6Ph$c$8D2Aklc=uH22dI_QyK$X7jvSC{#njMAkD<%s>eP%ork1${EfsM-zJb!m^_AddGaN7(U&MnuQ%jr;{3( zn4%TA$H4>_a&K^7;0D_0tut#zqNt=VLPOpybxf%408B($hC4*$pem;=66jS2!sJW9 zca7fnN+3+k``i9H7!wvQBbKIMaW9d3c9xO`Ha0dj1e=SiM+C9y1Zf5j-N;xQ8DN(J z-lzsu&7>?}6wGg;f&8l4|D}j4t%!b}Wj%I+hSJFp~Hv{|X|NYq*4GxzsHB&sx9BD4A}VZ>EE}6R9p5C@SQmTz?K7t@auEz0_4$ zLJw8zn%0u?H9{@AQ0v;Q)vSzS{XY5&k0;BPQR^Aew6QQJN3u)yTUnXyF^UTP>)AT5 zBeQNR8Z}DJQIiESQhy0OxXwp+`3rCv?e_a|`M3GpjpW)IowB1QFo)|2omP$IhI5ru z>|NLJ|2RC)8Y*h+uhRGZx4*P_%~s3D&v{}i-KN|+DVLTMJZR$GoP+DEU^;)QPr%w_c<=d=((R7%W4LkT_2pFnSsM z9;1tIo#9?ar}6vTX)G3WkPY-maS^V+d%E~t+?uah28P3GUnEFWjUSZHs2UfHMD%df z%q*@3g9EZAL`dJDO4u`{nGeZIWN1*4)47O-OAD-)7Y-jjxOZrHP@>-|ZK-5WjULyc zl{B+OM#vZvJUft?vQ1GhC8KXkTy z83qr`R+xC;b~C)9MS#J>TFhVr2GYY#Lfa10!)+#@tWDd9y;iS7Tlx*0U^)M&7~Soy z`~jxXYL7i?gf!6=HG%_r>D$#!^iuVUjV2aBR}C2l9feuRtVfmQDmMc0%_u|ws&#op zC#$^qwy1Gsg`nocruqk2035qUSR3V?NOuB9hiD+1fQxJfkioapQE`Kt z{($>nII;ae%H1(;nln2ucg8(&A%6JsuB5qi-1J+MgAtpP<`S4*k!G9Tm+~~l_RrfK zmzpM;;z#ebzr6KC+X_X?MMUtca0pUx`G*eIZbMXmGizJOO0A_E`34 z-FtOsX2k@Q@A5Z><@Awt6OdfCz{>zT3Gp$&DmT5v`oi2aFeD9!y45gbf!z$X3rekFT+ISu)-smx!sN2}U@Qb(!w57%U~&Vi zD5KEiX{;)YER%P$YN*~4#^NJQrduo-`Nbu-SPJrsN;J79e`ZyYlK`4k1oG-F_M+0f z_{4&OTO1%od5O8HMN*Ru*p%HBfU=rET(1GAc~I%cf$l1~iBf zWTGyR_`uA_$atH9|1N|0T?VC3YzmC>pWGNZ7%e}DF|hD-R9#}0yvf4R>h^(|fkmoF H7^njPeGh?n delta 274 zcmZ1~u%D0bG%qg~0}!OTxTddWnaDSj(PQHZJ;uo#Omd9Eo7I_`7$^T>p2&E3av#f% z$?2>LT&zIF%s~A4#N>&rsk&GWji=1f%3+Hg;tTd7yq}ATD+Q5)BM@ zxJA2d8eHyhi7a4Q&cBdZ(AUj36U)fW!x8Mn=Zl4E%Q)#P2dFePWYhl>cPK%xL+6XEGm$H~@*RLlyu4 diff --git a/src/rupload/app.py b/src/rupload/app.py index e7101e7..9c94a70 100644 --- a/src/rupload/app.py +++ b/src/rupload/app.py @@ -5,12 +5,26 @@ import pathlib class Rupload(web.Application): - def __init__(self, upload_url:str="/uploads/", upload_path:str="uploads", max_file_size:int=1024*1024*50): - self.upload_path = upload_path + def __init__( + self, + upload_url: str = "/uploads/", + upload_path: str = "uploads", + max_file_size: int = 1024 * 1024 * 50, + upload_folder_quota: int = 10 * 1024 * 1024 * 1024, + ): + self.upload_path = upload_path.rstrip("/") self.max_file_size = max_file_size - self.upload_url = upload_url + self.upload_url = upload_url.rstrip("/") + self.upload_folder_quota = upload_folder_quota super().__init__() + @property + def is_upload_folder_quota_reached(self): + return pathlib.Path(self.upload_path).stat().st_size > self.upload_folder_quota + + def generate_upload_url(self, filename): + return self.upload_url + filename + UPLOAD_PAGE = """ @@ -129,6 +143,7 @@ UPLOAD_PAGE = """ """ + def format_size(size): if size < 1024: return f"{size} B" @@ -141,13 +156,21 @@ def format_size(size): else: return f"{size / 1024 * 1024 * 1024 * 1024:.2f} TB" + def get_images(path): images = [] for image in pathlib.Path(path).iterdir(): - if image.is_file() and image.suffix in [".png", ".jpg", ".gif", ".jpeg", ".bmp"]: + if image.is_file() and image.suffix in [ + ".png", + ".jpg", + ".gif", + ".jpeg", + ".bmp", + ]: images.append(image) return images + def get_files(path): images = get_images(path) files = [] @@ -156,6 +179,7 @@ def get_files(path): files.append(file) return files + def create_images_html(url, image_paths): images_html = "" for image_path in image_paths: @@ -163,6 +187,7 @@ def create_images_html(url, image_paths): images_html += f'{image_path.name}' return images_html + def create_files_html(url, file_paths): files_html = "" for file_path in file_paths: @@ -170,7 +195,13 @@ def create_files_html(url, file_paths): files_html += f'{file_path.name} ({format_size(file_path.stat().st_size)})
' return files_html -async def handle_upload(request:web.Request): + +async def handle_upload(request: web.Request): + if request.app.is_upload_folder_quota_reached: + return web.HTTPFound( + "/?message=Server%20reached%20quota!%20Contact%20administrator." + ) + reader = await request.multipart() field = await reader.next() app = request.app @@ -212,32 +243,55 @@ async def handle_upload(request:web.Request): ) f.write(chunk) print(f"File {filename} uploaded successfully.") - uploaded_url = app.upload_url.rstrip("/") + "/" + filename + uploaded_url = self.generate_upload_url(filename) print(f"File {filename} is now available at: {uploaded_url}.") - return web.HTTPFound("/?message=File is succesfully uploaded and is available here:" + uploaded_url) + return web.HTTPFound( + "/?message=File is succesfully uploaded and is available here:" + + uploaded_url + ) print("No file uploaded.") return web.Response(status=400, text="No file uploaded.") -async def handle_index(request:web.Request): +async def handle_index(request: web.Request): image_paths = get_images(request.app.upload_path) - images_html = create_images_html(url=request.app.upload_url,image_paths=image_paths) + images_html = create_images_html( + url=request.app.upload_url, image_paths=image_paths + ) file_paths = get_files(request.app.upload_path) - files_html = create_files_html(url=request.app.upload_url,file_paths=file_paths) - html_content = UPLOAD_PAGE.replace("[images_html]",images_html) - html_content = html_content.replace("[files_html]",files_html) + files_html = create_files_html(url=request.app.upload_url, file_paths=file_paths) + html_content = UPLOAD_PAGE.replace("[images_html]", images_html) + html_content = html_content.replace("[files_html]", files_html) message = request.query.get("message", "") + if request.app.is_upload_folder_quota_reached: + message = "Server reached quota! Contact administrator." if request.app.upload_url in message: - url = message[message.find(request.app.upload_url):] - message = message.replace(request.app.upload_url, f" {url}" + url = message[message.find(request.app.upload_url) :] + message = message.replace(request.app.upload_url, f' {url}' if message: message += "

" - html_content = html_content.replace("[message]",message) + html_content = html_content.replace("[message]", message) return web.Response(text=html_content, content_type="text/html") -def create_app(upload_url:str="/", upload_path:str="upload", max_file_size:int=1024 * 1024 * 50): - app = Rupload(upload_url=upload_url, upload_path=upload_path, max_file_size=max_file_size) - app.add_routes([web.get("/", handle_index), web.post("/upload", handle_upload),web.static("/uploads", "uploads")]) +def create_app( + upload_url: str = "/", + upload_path: str = "upload", + max_file_size: int = 1024 * 1024 * 50, + upload_folder_quota: int = 10 * 1024 * 1024 * 1024, +): + app = Rupload( + upload_url=upload_url, + upload_path=upload_path, + max_file_size=max_file_size, + upload_folder_quota=upload_folder_quota, + ) + app.add_routes( + [ + web.get("/", handle_index), + web.post("/upload", handle_upload), + web.static("/uploads", "uploads"), + ] + ) return app diff --git a/src/rupload/cli.py b/src/rupload/cli.py index eaf1d0f..080f258 100644 --- a/src/rupload/cli.py +++ b/src/rupload/cli.py @@ -1,5 +1,5 @@ import argparse -from aiohttp import web +from aiohttp import web from rupload.app import create_app @@ -29,12 +29,23 @@ def parse_args(): default=50 * 1024 * 1024, help="Maximum file size in bytes (default is 50MB).", ) + parser.add_argument( + "--upload_folder_quota", + type=int, + default=10 * 1024 * 1024 * 1024, + help="Quata upload folder in bytes (default is 10GB).", + ) return parser.parse_args() def main(): args = parse_args() - app = create_app(upload_url=args.upload_url, upload_path=args.upload_folder, max_file_size=args.max_file_size) + app = create_app( + upload_url=args.upload_url, + upload_path=args.upload_folder, + max_file_size=args.max_file_size, + upload_folder_quota=args.upload_folder_quota, + ) web.run_app(app, host=args.hostname, port=args.port)