From 823956395b8e3d9c912f3307eb2ce3bfb1606b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Fri, 17 Feb 2023 18:15:02 +0100 Subject: [PATCH] remove scrub (#1524) --- lnbits/extensions/scrub/README.md | 30 ---- lnbits/extensions/scrub/__init__.py | 34 ---- lnbits/extensions/scrub/config.json | 6 - lnbits/extensions/scrub/crud.py | 80 --------- lnbits/extensions/scrub/migrations.py | 14 -- lnbits/extensions/scrub/models.py | 28 ---- .../extensions/scrub/static/image/scrub.png | Bin 24041 -> 0 bytes lnbits/extensions/scrub/static/js/index.js | 143 ---------------- lnbits/extensions/scrub/tasks.py | 89 ---------- .../scrub/templates/scrub/_api_docs.html | 136 --------------- .../scrub/templates/scrub/_lnurl.html | 31 ---- .../scrub/templates/scrub/index.html | 156 ------------------ lnbits/extensions/scrub/views.py | 17 -- lnbits/extensions/scrub/views_api.py | 107 ------------ 14 files changed, 871 deletions(-) delete mode 100644 lnbits/extensions/scrub/README.md delete mode 100644 lnbits/extensions/scrub/__init__.py delete mode 100644 lnbits/extensions/scrub/config.json delete mode 100644 lnbits/extensions/scrub/crud.py delete mode 100644 lnbits/extensions/scrub/migrations.py delete mode 100644 lnbits/extensions/scrub/models.py delete mode 100644 lnbits/extensions/scrub/static/image/scrub.png delete mode 100644 lnbits/extensions/scrub/static/js/index.js delete mode 100644 lnbits/extensions/scrub/tasks.py delete mode 100644 lnbits/extensions/scrub/templates/scrub/_api_docs.html delete mode 100644 lnbits/extensions/scrub/templates/scrub/_lnurl.html delete mode 100644 lnbits/extensions/scrub/templates/scrub/index.html delete mode 100644 lnbits/extensions/scrub/views.py delete mode 100644 lnbits/extensions/scrub/views_api.py diff --git a/lnbits/extensions/scrub/README.md b/lnbits/extensions/scrub/README.md deleted file mode 100644 index 3b8d0b2d7..000000000 --- a/lnbits/extensions/scrub/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Scrub - -## Automatically forward funds (Scrub) that get paid to the wallet to an LNURLpay or Lightning Address - -SCRUB is a small but handy extension that allows a user to take advantage of all the functionalities inside **LNbits** and upon a payment received to your LNbits wallet, automatically forward it to your desired wallet via LNURL or LNAddress! - -Only whole values, integers, are Scrubbed, amounts will be rounded down (example: 6.3 will be 6)! The decimals, if existing, will be kept in your wallet! - -[**Wallets supporting LNURL**](https://github.com/fiatjaf/awesome-lnurl#wallets) - -## Usage - -1. Create an scrub (New Scrub link)\ - ![create scrub](https://i.imgur.com/LUeNkzM.jpg) - - - select the wallet to be _scrubbed_ - - make a small description - - enter either an LNURL pay or a lightning address - - Make sure your LNURL or LNaddress is correct! - -2. A new scrub will show on the _Scrub links_ section\ - ![scrub](https://i.imgur.com/LNoFkeu.jpg) - - - only one scrub can be created for each wallet! - - You can _edit_ or _delete_ the Scrub at any time\ - ![edit scrub](https://i.imgur.com/Qu65lGG.jpg) - -3. On your wallet, you'll see a transaction of a payment received and another right after it as apayment sent, marked with **#scrubed**\ - ![wallet view](https://i.imgur.com/S6EWWCP.jpg) diff --git a/lnbits/extensions/scrub/__init__.py b/lnbits/extensions/scrub/__init__.py deleted file mode 100644 index 29428af96..000000000 --- a/lnbits/extensions/scrub/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -import asyncio - -from fastapi import APIRouter -from fastapi.staticfiles import StaticFiles - -from lnbits.db import Database -from lnbits.helpers import template_renderer -from lnbits.tasks import catch_everything_and_restart - -db = Database("ext_scrub") - -scrub_static_files = [ - { - "path": "/scrub/static", - "app": StaticFiles(directory="lnbits/extensions/scrub/static"), - "name": "scrub_static", - } -] - -scrub_ext: APIRouter = APIRouter(prefix="/scrub", tags=["scrub"]) - - -def scrub_renderer(): - return template_renderer(["lnbits/extensions/scrub/templates"]) - - -from .tasks import wait_for_paid_invoices -from .views import * # noqa: F401,F403 -from .views_api import * # noqa: F401,F403 - - -def scrub_start(): - loop = asyncio.get_event_loop() - loop.create_task(catch_everything_and_restart(wait_for_paid_invoices)) diff --git a/lnbits/extensions/scrub/config.json b/lnbits/extensions/scrub/config.json deleted file mode 100644 index 93eb871ae..000000000 --- a/lnbits/extensions/scrub/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Scrub", - "short_description": "Pass payments to LNURLp/LNaddress", - "tile": "/scrub/static/image/scrub.png", - "contributors": ["arcbtc", "talvasconcelos"] -} diff --git a/lnbits/extensions/scrub/crud.py b/lnbits/extensions/scrub/crud.py deleted file mode 100644 index 1772a8c5b..000000000 --- a/lnbits/extensions/scrub/crud.py +++ /dev/null @@ -1,80 +0,0 @@ -from typing import List, Optional, Union - -from lnbits.helpers import urlsafe_short_hash - -from . import db -from .models import CreateScrubLink, ScrubLink - - -async def create_scrub_link(data: CreateScrubLink) -> ScrubLink: - scrub_id = urlsafe_short_hash() - await db.execute( - """ - INSERT INTO scrub.scrub_links ( - id, - wallet, - description, - payoraddress - ) - VALUES (?, ?, ?, ?) - """, - ( - scrub_id, - data.wallet, - data.description, - data.payoraddress, - ), - ) - link = await get_scrub_link(scrub_id) - assert link, "Newly created link couldn't be retrieved" - return link - - -async def get_scrub_link(link_id: str) -> Optional[ScrubLink]: - row = await db.fetchone("SELECT * FROM scrub.scrub_links WHERE id = ?", (link_id,)) - return ScrubLink(**row) if row else None - - -async def get_scrub_links(wallet_ids: Union[str, List[str]]) -> List[ScrubLink]: - if isinstance(wallet_ids, str): - wallet_ids = [wallet_ids] - - q = ",".join(["?"] * len(wallet_ids)) - rows = await db.fetchall( - f""" - SELECT * FROM scrub.scrub_links WHERE wallet IN ({q}) - ORDER BY id - """, - (*wallet_ids,), - ) - return [ScrubLink(**row) for row in rows] - - -async def update_scrub_link(link_id: int, **kwargs) -> Optional[ScrubLink]: - q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) - await db.execute( - f"UPDATE scrub.scrub_links SET {q} WHERE id = ?", - (*kwargs.values(), link_id), - ) - row = await db.fetchone("SELECT * FROM scrub.scrub_links WHERE id = ?", (link_id,)) - return ScrubLink(**row) if row else None - - -async def delete_scrub_link(link_id: int) -> None: - await db.execute("DELETE FROM scrub.scrub_links WHERE id = ?", (link_id,)) - - -async def get_scrub_by_wallet(wallet_id) -> Optional[ScrubLink]: - row = await db.fetchone( - "SELECT * from scrub.scrub_links WHERE wallet = ?", - (wallet_id,), - ) - return ScrubLink(**row) if row else None - - -async def unique_scrubed_wallet(wallet_id): - (row,) = await db.fetchone( - "SELECT COUNT(wallet) FROM scrub.scrub_links WHERE wallet = ?", - (wallet_id,), - ) - return row diff --git a/lnbits/extensions/scrub/migrations.py b/lnbits/extensions/scrub/migrations.py deleted file mode 100644 index f1f4badef..000000000 --- a/lnbits/extensions/scrub/migrations.py +++ /dev/null @@ -1,14 +0,0 @@ -async def m001_initial(db): - """ - Initial scrub table. - """ - await db.execute( - """ - CREATE TABLE scrub.scrub_links ( - id TEXT PRIMARY KEY, - wallet TEXT NOT NULL, - description TEXT NOT NULL, - payoraddress TEXT NOT NULL - ); - """ - ) diff --git a/lnbits/extensions/scrub/models.py b/lnbits/extensions/scrub/models.py deleted file mode 100644 index 8079f358a..000000000 --- a/lnbits/extensions/scrub/models.py +++ /dev/null @@ -1,28 +0,0 @@ -from sqlite3 import Row - -from pydantic import BaseModel -from starlette.requests import Request - -from lnbits.lnurl import encode as lnurl_encode - - -class CreateScrubLink(BaseModel): - wallet: str - description: str - payoraddress: str - - -class ScrubLink(BaseModel): - id: str - wallet: str - description: str - payoraddress: str - - @classmethod - def from_row(cls, row: Row) -> "ScrubLink": - data = dict(row) - return cls(**data) - - def lnurl(self, req: Request) -> str: - url = req.url_for("scrub.api_lnurl_response", link_id=self.id) - return lnurl_encode(url) diff --git a/lnbits/extensions/scrub/static/image/scrub.png b/lnbits/extensions/scrub/static/image/scrub.png deleted file mode 100644 index b3d4d24f243b2cc046b663b3db863037fabf5d35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24041 zcmeFZWmsIzwl3PZyIauU(v8!&y9Rf6cM0wq+#Q0uySoz{f`mYD2^#$HeQWK#*Lv>x zv+q6U{@Os(-Bn|}V~n@nnzQD7syk9iK@tU#5D@?Xph!!Jsk}c2{Plo`eg8iwU^EE; zP(gaDYPzZzd5}3eJD6M9nvuDBIhv7~d0LqR0G{hhS+c2AG)bWcRfTDNPxZuoJK0;p zEWN$5Vqc3BsULk7Wz@{n#fo_i&F_tN&Yx%f4ekw|SFR(N)0R)lmaYvxbg@1ZJk9!F zzmRmKfXyXtuIqP$Ys^?7_1dGUK)Ir(t_ndgv{H<8EE)ay{y+XK3~e|%|0 z@^wgNFC0U=>z@0gPdhwI^us6cAtSZ6s8vwWC}-B=i6iOt;pdHp^~Jg%-owjwd%d^1 zCurDHMJl)V(<3U`k)pHJm8hpb8?7JVv+mY5&+vtmX1u?4Y2F(wWe1`4>nPgGM|wfQ zP=CM8mk-s%y`<8;OwKP4uU~3Am0o%19gf~y55D&b4)^xh(|n(e@YC^qX`qq()Azn~FlZ40&EBoVFb`CaN5dDjDLkW;lKHvN1TT}vVn5pohn%sAyZ=(X*! ziVPb4Y5X%B-$U+VI9Hq4saML}Hm#e?>TUZF z{SP!MDVDiNG~6EliI410`T-wzmqYtQ#GoUzr9Lk1=)^EV<2GRBkI$J*IAH`T$*{u` zxX7fe-jwNFGca|18Nu{g`wcdfppvO5#~`YRG2GW3%S(mm<&&jvPgap-=#F8vsc28t zwyA_1UQ?N@Nm19a>5k>}Ic`tW_c`hQA|OeOFvnOF$N7kFqHxaBezn(1Lz?a~oT9Ej zT-~vLY*W=PotNXW=GMA-zq(NP5lXO1yU~8|7ecry_#yd|BJWEK8%w!+Qs+aejzi~5 z9It=j9m>ge&#U<20GIV|aT!uuLFJ!I%YJ$k@Cs4J5`BgVLPJ?1LL!pGQ}^*Ms(aXM zf&sm%6v2#988G58@V~H(+ka@B>OPC9COioaPd7iOwGF?qJ1Z1Cr6oN1e1E00rY2lx zG0vl3EPNEZ-OM&Wjj_0>zVMB@_4D=U?Y+$NdwX*w7j$Q64EKs-DPL*X2<(d-l(Gvo zy_{u-s>#ap;0DZI-IY#b?gW6&Iukj(eJ3$c10+jom3xVn^{e6g5wu7wiZ_iL&yIU8 zBz|3xeFpW8#bAgsn=-D@hQ#BwGGA;Dr@ZcWOg^o zCnY9)uRdXW{=LIT%RE%An?5M>zN;~)CjU#ycNML<9~@C%i#d+v&$QQK=eHVsz-eE2 zvO1@XO-7shLQv4S{&eUdeN<+#z`(_2omKluz_Dt^&34vpoTIMJBT*t6-{;%xBmT&* z=Qsb^jN3v3U@X>q`=LNDZ8)&er@SYRje^_pB)fEY3F2+&na0Gv^^!jTk|9inivHe& z!(pbNh}`g|A2U{oJgw;akDrar$j>b~(OFsj`=8E+T=57DQ9wqF+ym`|t=X0djpdFL zoT&q1F60;&%+14@ZM7q(6&Uf2E{%wB0P2xEt@{>D#f|``hZF)uj*`Ah3He{`l9|mQ z`MJf$3c!Z<{CJnsJiCSCq-W*rmO^_@vrH>%yPxeAR5)sWgz(pb8)l0s4!W<0yAXkI z5o&ZctZ*mAk3V7;$D+I)(yMxF^9{F%isl*;B!p|P0g`IZo>W+YrH_p^)$vwhAY)tRb*4$hahTM)~Z5iE*(0+ z=5|*@R(A`6lOlti&*7Z=q6pHMyEV`2Orjopm)B0KlSc^0D^$jk=(Y|M9z=zzcN1&8 z9xSttBNx=95L9X&7}th(J9g>GL0ZFWgz-Rv7>#-T#9lI&Ho^%YNe!kT4U^&t z&=beEa}GYFFNm*CViXhBbN*^TEsE&h`l@_-##d~ z_nP_2N_c6z36@Il78+$6)V<83eBe4RQlTpzg~61vSiD*f$FXrzsM`(0L7Fj7@@I>U zJeQ(BiK#_9c6q0xdm|`ePbPTq=bR4BGEnFU&$+E{K-G9VW z+l1&?T2W<{WD7%tU@wu&`xDu?e<{)bwoPK(C`*j4aW>LRP06$XXMDS%K~j^RP7ePl zboxskSx#%T>?(&oO1+=5E|b6=GOLA>--9gTWv@kwf3mb+x3nZAX3a`>54n+oa)N4! z>mueOJfefPUv4)LTvOAjsYr_sTij&Rm?gmD{#iFEN*F3Zdk4YD#9PR1dma%2x-$!= z+T5+1Eb(h_#EFbac+^xBvYrTlH(Mpzf z0o_~)h9}i9;s`TB%E+}?-|0YbF?m{pN523hSEqG%?X|{C_ELA6f_okGy*(3XpJZLs zDfbViD1V`b;kDuHJMy*vqGj>?23t9wkBE*|B;`(=XE@zpB`4WWI zGFQh3X}3QfoAx<8}>?De5hWn+LT4VKFB(wc}29bBu9ZwBq>icukr= zqw&fnpN~;x_7d?_+{@#+?1qu&p+YfU*rh{M(GcKqVaCbPJmRCwgm)duq9c3Ro1m-M z#~jF(r%!o<9FdCYe{gauPXr7UlrWt&1Z+P(j48<=#{&ka?By7~4lkLc;C#gByW>W4 zW*DeG%xhe7UqzCFE;Q*$M$U(GF=%tV%JEn7rBWU@vK)BHeaXH}I+m!tVm})9N-=t=WuP-s{m+{8s!L(0Kui+YzeTIdkYy!A#Z6(xGi?-@hxtj5nGCr+X&-x?Obl6HGjS?H*S zlE!xO!uwH4JC&7GqHXQ0gjVso(Q>wtWvfP1`J5c0_XtD5!Gy;C3>>j4G>D3N|h&9@BOn5eirE&Yut0J(N# z@~kOEnR!_$g^|m7K7i=^1D%3hT5{R+;tLf;siAKlTyh<$fc()7^rGsbQMj!mw-PQ) zk&5t~VPjyJ?{{05(U`vA5Y3jB&t(4Rwh>IfczvjO@-w4`Ar@uiK6u3uAuQenwT^AX zV7Ysm7Gn=YMgZj#%s2KSHyUbw>o0<#!$0T9Ofd(_%G2V*mM;akCV4t5;$PAuZiz}~ zW&0IFvH#{Qf^=#}&dgF7I%*Z?CKG{2p7ylY&!<9ML>U4JLc|_ma9y+3HT|AMsI2cSyAse^hB`hqn~JczKW>!q-L_pD6XZdhFA z&4@q<;U0j7x=nH`Y>zE190POcF+V@%G9C(B&L|OJRNQuoks|ztjv*I}Ev=6ieC^SQe&DVzN9HO4_5AZ~N2?lni&#o{@+Ky^In_qYnQ9#91~={gW=p2vL` zwGZgm{n#DHQhA_Hh5tu^<=)LtCgm8s%C?4M!qd+{{ zSAU8L5@P$56x-g`F5y&=iXPavwfpH$Bzy9U$@m_L+Fl4T8Otb>N`ER|0}vr~C+_nl zx>}vmSFtZ0c$yZ7t3~C}U|35`X@N`VgV5wtg^~gEXbL*Yrv%cEJLXJal zyB+$xFzwa+tnBObCG{P++zN6t>c{uA6#VtqiVA(!AQ(LtpR?@GFZPNtP&e-?I4b8LmXE|a4LSGbEgh48ksAl>T=3&z&X|m; zh~_&vp;f61eYk;MMgM@R1=pi7|1bdbilM`7#c~eC2`MN<4uIOF%4R>6Ef2zSFw0mX zsG4-*Ry&biJ^U&FK|>6(cL3oB2+QZM{drD}Lkc7)$}3HbN%6%tv|binOCGDr;Hn50 zPLQLe4pnc|g-3TxjAW08l8<&TTue}eS`gJUI)G$Af^;lc3~k>5W(W?^$DB?$Kz>B84ANAhZ1!2KhAbA-LB6Qqf zXz92ID_lK?lvsom46qQJ*pb=_ucv1SOwu55{vwnQm6&T#?$<#@$mGN17xQlYvLd?> zTjAO76}qTZ#Bh^NxAzSm2?1`1!gUE%$`QNo&c2OO_P3wRx1#L9ID^g{+@pvl4h5aGwB5>zOD@hE@6!bq3RNNYRii$n=HpuL5f7V6GfOMdA;Bn2H zxoPpoa9a`I~2b_N(yelBn{wAFWFANoMUEIN-IMV5we-#w@> zMpv0#boL3@)a$!G-wGDcd|IM`!9c{8e&5L=CHmRbYWX;6yn4 z^(*_m502p)kRVuc0UMBKzC4N$Z+tt-GuAnhE+A`>zgdIKQ|c1_Km#D?`teHL=OgV$ zX1d+sMzUTlw(ma4QQR^0gMuh$^LW;*6%3V}v1}O&@H2xlEPCqD-P(#ArK9QlpBjQ&|GjSZ%uQ1Um^~UE@6I`yzeDFe*xCQP-4b zWyL5iS&}TC9|>52SB}O5=g|skZQQUSYl&JSVq=Re!_I<#_Zpb%G7xHqG@5c1yRRs$ai(7n~{pGg*X|##!8ML`Ps*6;(e zF_0dqL7)6ggxNR&g=!iSb{5!dDdiC{Uk_7~V{~OSU%>>RQ9|KC!iiCBTcq%QA^Y{an&u z3G#w|>SMHMW3!W4g1N;!>%8Fkx!vNYETaom*h9sR+$rRWZZeS=hZLS*=IHWrOdH38Y>|*tN)ga0rI(KH1Sh?zpVXP5cTDH^DLDoAPxs$^?hfZ=z>p|9u97Le2P(%B{Y9oRM9;^NOtd7JX z94b){HIf36sydix?>|C(R1vGd;@#&LaT{#eJ>Wti!q zP;MYIomV(Wh}9c6(nnyI-0JQZ?%BkhS9$4yev|93NKwhKV}Se-vc5YNlp%gu+=#-9 zRccBObRjXRq0qF|8oK1` zRF&O&shNN(TC;1XEte^~G>lyA&<%q4wJnQ3|H%M4TqYH?C~4GK{QXq&{`lpeYA}~* zqC80v0X*qqL=D~7Mx85C>)#i=e-zu|b=S?)RJi2_il0U!dU7@yUP-?o)Z~3_K?7|` z-VwXSw`(1Xp54ltW`%tALco)##8?VNwlr>uT8D&jog-sP1(b+eg3Rb0EXzw!PpU4M zmr5ALqhUBdaw-#I7;?Ri9j;y`OVR^i0Stt8=s7v!X-iFZ6{VaOL>t0g2R#CpHAQS zi_4WtF~+d3scY90LpFTZ*_06q(g_5 z|E^DXQX6gDp~|s~cgR6NaKK0kIsODU$HK>pJc=()9a3>v%u?|y9kqizKPc{FeklFw zvNTsVx(IiVSeTKLBBLO&O8hyzgd3AECT3qYVbqk_?o(X?q`vKFik^^<$)fm!4$44v zwFyFgq(&dTwnn9LSvBgkTgm#;jf^G+S3yg%!Urecf<$_0`Rf8Gu{IahPu1>JNSCqd zi4JA!GVTH}V={%Si&Z$7MgiZv{X8w)7By564Td5C@$6YNT7@Wk;@jB!4@=lyl+ z4zfo5he2SJj|U5>hh8pLz~Iwh(e@U$zv6MVC22>0cOZI__sQp&(9uLew2b~Q_Y2~f zN-swwIfr|=kSsCvO$b0tS_7*~xL6!^X z9HxeZS{96Ch{q;U!iA>F>uMxIushpEEHU5)wwtq7v@81jGEVOuvS#{%X`JvlMe^_U zZpYi^cFKKXW4=lx4@Df_)t?b-j1iWG;dGPSp;g4X&_@ejN+UM;RAB``l~(7K?qyC! z;9x1`j~+I*k`@qsK2+2cnxh`Sssk7hL!-^mt?3XV>_${Jiki5f{bPTy250&5s4 zeVIdvTgNdhlG{&7Ws^BH;TQu(*V?&(bM(srpOnvbA>)Vlya7WayuOj4aO4TS>r}v_ zSQYn}KTzS*M4~i!=y%eKD0-GI$qD6k`2}TS{!GsPz%8ilJsSFM)SPbdB5V>Cr{do^ zU{$te=_nr+Ne$m(py_YAQV}_>^(n$#Y$lyOu33_JocdI4T6DH^_^y5kl|ru{z?q`D zpB7R3Wj|XT1$9Wc780)K-PR)>m9YY>0AU9uCaa7j9w_{;^-SR#06NzYm2k9hg)s6^ zTm6T_2n*^?gF#6qDOU)MFc{)-2lqwyrGCCE_Q2$kxjkh3^(mciv0pyuRx3fSqkYoqK;Z$LV2_6G2cD<3x6_h<=xDQkEQ21|Cr}{2Zf_qiiWpU!j*utDOZt{46&8 z=f%2O@vMl7s3cgmPg5YSgS2+IThJwlF5m@AJb>01T62Y5TIsaW>qs(ZkEcbIiCpg3 z<~gLbA2K6}>slfk`JwchM(0U9eM z9XQ^iK}OhTs3gwWrs1IvI0Abg8e$={{wB&|3kP4%8n2YvN)-~Lb@Js7Xy>S0OZb(r zt09|~n8PcSHdHmZKFi(V-Z{|?YG}o&~enSl&aD}$Dg!eTkx1>_}VI{G{DPJgtY{mON==a z!5de5WdwaOB{V7v{kpk+0x>>9k6Bwje$9$A_pKCc;!_0`*8j8JgsB5%$@} zvFQ}!yAEttGtn*#Ft%#Y0-es(cflM+JeqREWUGeKJJhx)o_81}>6mz~BU7oG_n1#K zq479GtLIp*Fq&`i1B^8iM2iCw1kZVsqW(3Hwf&%6nC71w?Wl$m>(!jEfsJEC#ky$& zE5f+!q3eBfWFkkZaGHT*N5?~P#8c`HIDb&60u%y_h?fLCC&OOHS_W5Qm!l@;6OQT2 z-=icWj6`a#6eaQPAf!RwvUnR@fkqV-r8dc37o4_M>9^d5r^(iLfHj zh~SifaxNH)UAmI)N3)Y5czrBX(~vijSqkNLK+4Wd_O8`Rx`Yhm-@&rTt}Xn*II_%CxVVvwTE*7>Rv5h0M&PBHLC$D#CP{P9X^?HEn_ z(Mu@DjND!tR{gUeHR^4&`%`d7PIJI%k9zW$qh;=KRch) zZZ4G{)zk#stw=8YzQ6u}4Y5CW4#0vT+zwWiWQKoPIa=mL<&{H4q$^&;cmFoqkpRjyJJ_!llINYf~0lK0dIGrr}g<- zX)f*ASZ0VO3bcr`B8pPgsQr!To*&(BhxxAm1{fu}15Bwjcj}LW$132nE#tbvJ1Xfm zB^iS(k}vfbO|aC=Yy2wsbaF{314p*AO{Q|PuFvj?Cq889I_FtgDerk!0A0hS@0+1741>ZkRE~ zBhkPI1PfXw1WyJQl}qt=e>5v?`7%>6RrN{>wcyu`oTI8zjr81i%0t4t@(Y6YOO0rO zRaV4Rb5#rJ{(Psx&n`+@(WkG<7Wwyc4B--2(NGv-XHzirRHVtTrV^H1= zlApCLk5lM(4$|kq^!qM0N0(f`FyDiq{^H4x71X#uDGYi5?^>6M0#N*f_;QP%S-bE~ za~6r7PVbSb;i`(+ZoM<75{rlW^#U{_mXaruKErR>(KFv5RzlQJutkH@5sox6=+_Ei zQ%f-gWur&Q~GUv664#4aA1A3;Yku_A zA|=txIj^upuEbfljXz<_Qbt&jB+Jcne;F{3G5SND_=fLk>3ZQ+>Y$>Q?15W8$z{lo zR>Il6jLdM9x-|Y_QHVeB;RYuBa1MxLCux3_=JwRdV8jHM5eX~J>i3?GTSFT_CvnyD`6fUv&S2fR|!`QiShT(002aYm8hta zw5aHR>;`(@1C;HXz%MnZgdM8*NjxD+lsAIgv`hiFDvH}0CrXKY5wRMa-gSeP$xcPb z92aEM-=8;J5ggrEgIW_r_6KVBc(?eF;^S5tw)T+ckKY0_od=g&z5#P(!0BT`IQC7> zh4GN|>FOx{T6nSu;BLg^6zeZ4I+*Rpj#B%IPW;)ci>JoNrLN(C04csnJmEko|4qYQs;VDX&B(>fmff#?H*n z3}h1bv~p*q5I`j3b2c>xtB6Vb6XN|HKZT{Mt0S0&#lypc*@KPQ!P$ZZ#KXhG0%T=j zWo3G|U~=)YcQx{4vUj2U3*sLbVrDKT?>ARntsLyh{=zgec5rj$r=WQ6C;N~5>>TCg z{}bNc<)19P^TFb2tW%JIFs1`rmrEsJ?G1t*EUu6ATZh!UsUCzHI^6vhhxc_GTAGQB&{B9*L4;FJUar-MhX)%6^zv6>U9ZalD z!GFIr=io8|a+sJg8S$92GO?Sn0hx?hK|D-sMn;?E~t4Ky_}Wn(fk<2GetH#g^GG6IxZ!P(B} zeK@V`j4aGp9PKUs?)Zyvu&|OeKLsl@@V{D=Y>iya-yQfVo9@EAcN(5RjSeAGm)F3;4a5cVdnH(&;QNiR>@WzvWHF_m4r5vT}L1@cK*f|J3{^GpB#N`^OZpwfeh@ zjO=gOf{jf65yZvF-OTjwK<|G4=rXZ1vbQjMpWpu!)PJ;F{ci@#nAI4_X=KXD^gb*` zOzdo?JWSl2CdN!aE-rQsQ`YyfH2Oz*|B3G6VD9Q+xeKp+Ln|NRo#%}va>I61hPjNe7f#BKz9 z7ZEGRyPSZgCMN8xW~}C{tpA?$|Hl$RY+xWO7{vPjUx`3&5E~DWhlh!io5zHS-4tlT zWDI0`pLakLRuC&Ykjogz@qeU5HYOm53CN}j;sJB;fZ5spy+l5izmCoSp<6zd|A(^w zVel^p^Y_vJN89^J;{BY%@}DQ2f6C&o$?$*i=btm`|6+u9=>G}w-{SXw==vYJ{#y+E zw~YTsUH?PZe~W?tmhu0n>;D*Ci2rrjYG(hwmi2hQD2+`ydwRd1g*BFy6a&2d^_$;a zn)Kd+;3%c#0stUk{q=wVWM<>PH^R9}%ZtMuKtN&fGMF2$)h}>~Jn967@liWtV!CaG#j;%^MFoZw^J_%aA zF9ZZDS0Cw=!iYDX_-rbxo~D1Xf46<%G4uSpvsSlz+xMb}KBLP-kV)ra%YerxueZ;yrgA_^eIbCsL>xkWBnq-B1_wryfB~_NRUO;V?EjsC z#~+~VYq3h1F0O+sdrqhHmCAXTfmGzk` zWJUEVC73DGyRP~}JpPdP-<4gx(a(7Db?4~c^dXBwfwp3540peX>Q?Lqt14i4tmart zza;rR+K5x%H+W%U8i|vuhbpUmQQinzY9ef`K`_c>gWopWo9~tQ;;P71eS1RZf4K4) zCP(;>$@T+W*LiEHpt=?b4(SUT)_vZQ{z5NfUmZpQtEm=BLj^=p4NRvMhlH0|Ki~AF zJ7H^Y)?T#Yjvg3Nzvj>yrti9MvM`5A|A|ch>11yT{x_UpWViR=RN<`Ic(ygA&!N@g zoR>krxhHcMk{p8a9RGcSXn{%DUq%`o+18ICHh7e=qH7ZuvN&+erixS7O_&JiNuyE9-Ik z8gF{ay&TsWvDJh|5IdU>&`#=hj9N^33sAV7-spw5GFDZcrj;u#OM=S8Q!q@t_tKzLVgu=L9z0}`e{K*SQ6$-X#9{MV2& z=JqQ?*B#|G_G>airA-ddZrw?#+X5Gc>S!L7byOeK_2aprL7f@92)>$Iqy7fbX)sxV z3{p`?j}io|PqfYt9%lUeXNEoI9Ml#7IPK%@vq#W$DaJtAcF24OOi>jkG8P|R3h^M( z;m`>ju&3@b( zTSn)(HmJ=cX4m8USab<9`Tp+jJ#iF30g*p(lISHIW-teiV1=K#0`T-gR>{#DzL9f} zb_+OUKEK)ZSBM}g+j9>){SkbYU`cZnI2^Qtm)|F1X)D&jcO7nr?g-^x#Nzb3-HcCm zZ14tTC!82P4+5tgS@Eeky^$?uBKvr#FM^M6h9g$no-r3@XS%L0 zKC+92xO)p%%NT=h?&jMsgIf|wq7~eB1{LGm$aL8*)<(=MdQG1pL=&V}yw*j&dZkAV zSR$jhwRQ2DPXl>aNKb?V#FHnlS$H4#XY<$t-bG2p;2%u2K{i6$D#T1od15R*eaz6fc zEeF)KcnJgMstnX90ND@v;IvROW-)wx4uKI`B@zc)=rdDDKyff3Q7(T;uGt=Q_DHuQ zttOy3D`L~n|7f81J7lcj2{K^La$Wauw6w>^c=3QZsOsDCG)(<9RR9uX0H=f-0>H7% z9~I#E;a(-`dni`mj&=w`eWto%X^XTEQz&7C_qB?bl%)1BUe7SU^7)(I^%C_2~ygXdM znM+679Up7yy5rVoPNjmglkI2>hO7@T@RKuaJ`l5f%hHb-Z?fw#6qCmwZBCQr+JQ2w zzN#A0uz>}2=|ICrpG)vIBj$kJfPS~1@<2-lAYXX_h|*=fpTO@E^gV$Twr1oq7Y@k$ zNsctRTMrvB@g94FerB8D!aF?L;b5j2qI>J zUaX0be_c8I)&;YyAKLno5!Gt~q#D+K?tRMCS+BD!U#i$VVkM}9eXFx^|7W6g2i*e} z5Yczm6Eaau?Lu?}ZU02qb!W0bBdfi-vaRU3ac-q<;;uw(4j14n4lw+51W>Y&lzKZ! zletcGC$?GX7IWyBG^i3*t!o+#ap?MT)A+{Ck4Y<$@2%xZAMNr?myI=>sOQ60&npn2 ztfiMfJQIr5ABoHsv()D8q@u$H3YZ{&n&?eV7Q>h)9BBO}S>UaJ zvn1D8VXnMai#rC0x>7&2xx?7{9Gk~Z7gQ77;2fq$2*r&BsG@@o5MLW?}|L!>bY@Vj=X*KegCt@y?1% zg1u;@&u?ka-B%SeVT=OCwc=MRmra_h`iUL@_V*vZ*C4f}ZHaujE!@1B`rf_VhNsYX z-c1G#PC|^6gutM?cDa;A0LcD&*^m}|!EwFAC|o&1QH9LwXBYu+ra=R`YbfmLRRS4P zAZ%A9h6mq1AZz6V=~JkD&Z#o+NMUF|)8fD4p3^U9vS|LGyO;}%_ElBfx}53Miu>Fb zjfDAj+{+QoWCV+EhRC26G)wFu*k49x~t&z8@6HQIOwB<8q@ntpMCM;Jb*CA0hF=|LKA`CX)u&1~N(o0{ zinH80;O((sDX{5O0W2APL_|4kOO@ZscN~@R)8&)ep^CaNjqrZQ+GkEBya;q^J~~U9 zsl2|(0s_omj)nR)E0-xJ2%~AuJ@SpMt7+BK4ivqA^SFjTI&FEAYf5WeFhj>TmSowO z8|v|AyEwoKl+J!o$Dt2caEhCE_?)^Y`xdpaeTGLmQ;59oCPljTrH9xOK%uLgKm85W zsHV4|O^fe=xO|YMki-jF8jKZ|GD_ibfW_`^oEpM&;eQbzXU)y%AgXMblY4&Kq592CGSca~ zTIz+eQTvAkj%(sptBN8ttD!Ju>|Cd$8ne?2=Y1{c6!%KD8bXhE@m)9(PhT`W;hBH* z!F$xdfKG%plS>{~&pMRL1hK85Ou3#=8{M5ahamS=>c!$xBK(=w^7&=gZ0uLH=Yau& zuJ4SF;?Hbw08sQbn-1-)B#O1N!JB_xXN$Kw--H?#=<#fo-D=Q*>`32~HOW%9!|Gx) znX_txh~zp=u*Sv`o(qNaaUezP!WX)TFCSf%aOkcpYe-7){6Qn?Q8`&hW&dQ6P-vgq z^DAWEBq;;tpyg($&tqsnJYDF5Te%QK2s^w%>lf1}qTvh`t}~a9jnf+Y*2ecQDuzE! zV~`Dd=)IXSvfJ&^>NmCp?U;+Xz{p!7CQgA>+Onsw+XMQ|MzE<&63_gC;mt1};;$87 z;d$e~~Y+7;FbQ5QdbW^+;hU*?aNgsYf!i=zK1@-kE_c3N1w5 zA>OALNC~-nX8e8c$6hxv!Ol<_+4IIVo?|!2@3IOD_l z^#7G zGTI7-NUIUnX3%YwsO90tIe`Zqizdu6bY|c2eSSW5{tkOm7UeIi7k1@@XisJdvBZ%u z<8Np|Xsm&$1m(Tuj&cIez-=$xZJT&bPvGaLkFb5?WT*HP+F@1JLuFP2Wp)D<4iaI5 z3zwk_3xONkB;0fb99h(fD#JXcy#XRV_B$M>OGMH1tuyA19UD#^%saQuMH1fgN6Jdf z1923)9Agy{QysWdVYpN4VFQR;`8HtGwFSGw#Ay3xJJSJFa!Qb?mUz#Q-QAg2;b8*k zLB@bT@QMbB&tk)YQ;=G+VBSkKzITQ1?pUv0*|aAF-ylchKtR{UJgGs`DpTdTaE~6( z34vO(>*tn{na`iz-$u+&BI8+-be|jPhX43K_1-j@CT^ow5nJ7%sskXT3hF~ez*hA5 z!_JtRYvcp^m_MlE^jH9A_dfg)UC6bYUy`d!ZHp2@Ihq zVN-2?N&d=g^d(n3CTDcwHjq#v3934tcEl+UmyE-*AkruRI8Py$qa26Il@w_^#N_aG zR9l==T~?c*3QFoD2q|lQ}TY-{9tteM#Cb_tn$(|n70QX&;~j37PzmXaRkH6z-VtNL;*&O2&hNl45VR zCymWf#31;LSgxX*+t;pgA|E{ti>bn^Sh_DIF58h$kG?9(RMvsLyP8xt+vsB+Oqn{1thaA?kz66v$h}0q-mD|}- zT{h_2Ce&yR#{(;t(mBII)l%KqFm;!!K=+6VB!gi`UW>kMjr%zfN{;k$lSP9+G|S+F z_{o=NnF5mVDILkNF1MjtKXr|8ip+lh^3`}=;fIG>^6qnwuGE8h2=!z6irH7TagJUQ z#WpvsfP#e;@n2(p-xq4-uyacWQ__hXsJot)3-zRG(_w%iCCt9LQ40o=;2c4_>ju;17}|im$4V ze6a(>J}D(Lq?n(^zjl5(iT`ts2lWI{{7lUz_G|2w;TRS1{Udd(ss@jsU#r6Cf;ooL zg&6CUi*MMK;rjg}dWlc(>rPP`^X==yY)=Raj5`TtO$gg^D*~VB!@dRhGv*`t;gmSa z5RpoDGd;z*?9KpP(?@Ne4;fHj(qL0JvF#O~Qq%wtO;LWw9lg;?gGgPvbcJeIpD1Ns zXN=nc1~1Tvls*YzGo_I}081_M|0d8@IG8t4Lq7UFG2j~@|Ke7y91YwF#xn{QVTF1(-}+TafQ zwkdr40P7G;FE-Y(spMrnQ0{yIOWypf`Z?Qqwd7o3D{hdrXS{R2MU{$VFA$o9;tRVD zMpZTJzbdM-%($ThUv8l#_#HdQDwzi^bvTWDh?cDYC^x9y_XbV5O=q3^1m}Fhb6#FLx$gPZoqLxFGpp|nm1|oiN`nJo_ zh8{*W`D?*8!WMCdZht&_#1Njt@;AHtlk;CU?rxU+VMQt$59E~R0v7+)O^qsp>)Jsqp;kwB-%gvAVG2B zTVS=%RiFtkG-&`w2ec-1d;*UX`ykxkRK9kah9RkHhg3%R|4EuOCLmrJ#`bh!^;*{t z?)rUS*RqL{E6J=9>hZ^)vY`}%lH~^lg@PBmuhz3K`*q~<=bL++nPaXZiDg^k}?#ZApTznLKtkA05# z&wOghErHe=b1vpoi!kEaU&GpZCm0bhH1;(g#EDek9sDau9Yg9|9tTX8d5`b<)m|F6 zE8k#p_zW^ykKD8myY&VzLlcE2NW>qU#;rxTUkQl@{djR#u*Ab(y z<#`7&@6`_yi9=-g4fNS0&aoc>8mH|^oVG&MOouCHc3~w5dNw7<9NCX~_d_L}KDsa- zK#S5N02u~5?3ZK<<>Ll3jJ4%XWGF`Voo`~p6?;x+g6?IBm44K5p7>UI_>$QB0n`MoL;=7 z!dQC?(u(>kOXS%@8A3?Q7tAfU(n%8SyQV5EJ}>5aU0^8CQXcQNI~;?{DJ7b}TrA6FQ6K z^kdi|uJ~|MeoA?<`Y9L713_t*#JKBs5O(>vdQ6Df9XyBo_IEJ7fdU1(j5x<^ zeHSuPna3i9($?rHJBKOWTHdfRH{L<^&=LC+8j&oOl7}+FP;e7uO1y^PyI?QH8kn zx3IUr2Vq5vs)-f?VT7^Q-+~*8k=y?_$bn}N+CvKqwdSKlcH9SM*kAd8P%duo37pry z0qx(z@J8^2hrDEyz4#pZ&i{46*g&gs%Ny{;U996rzvsAraEXXuS^m?mvK*htV>M zYIr}PJ->{M){d`zP&slJUM2UFKSo~o8p0byXb-71;9!ovhV%M2{brV8`l|>Oq(>LL zY_;~5tU|}CYa)Ed&&`XpT8jEXIj68mgz(mV4C|(kBEtTuTAIAioxy3o3ZZv zJ-l6?#NPYs$m-R;l|ZAlgLCdB+~@ujWAFgvy8$U7&`5t(qY%TV{4Tz*p+?ZX zZ=iApqHe7pB?MFfO+*UgJ^y>oL#}Ivr!Zj6L)h0njIhFm$0fQcvPT}nIR7nJ=td6# z%Bo_x;Vu%gY)P$vS<`@*oX2UW%0X+J(7LS)-l}i>(fi9jGdC?1NN)_?dkBUPfzC~S zTZ}6~8v0+y8_Oc=)*`^>>pJ;U!f7AtkcB3g_)3`Ih-}(1F1&%=Onz90R`$ zAh0kaAax3%-05ptclZ`VB&x@AfxaXff$d zv`6mJ5k%i}2(1^bv#=X(B!`I*;4Z_Co%sU7%)#$2I8$i+(H!al<_)dWXYjf&K)e}I zQ4hi@*a;)h`K+EqM5>StThSRCHGCGm`4R-X+XFF_spTWeKD6rRAj0Xk~D#K{ridV4}d)s?4;`N0fLu=3yq(ItHjHd6m(FFhi2;fOXK~ya$qZZwF z7U>Ny&?Z(eQ1@;|?7F$0qq#6ZSXD>%*nv4?0m9YTYq!k%=v}#d8#6T`eH`z={~&wx zJHZDij&Ix)8WFA`y!G7}<&6ajqLquA=tb*nK5HZpb~*O755nG0AKlR^n z-+BhT^pv6sRvx5rQvxbo_`|n?81pTDO!lC$sBlm z-dI2e$LCAv4zvch7yZWP$?X3!YP2Kp#LwwLqsARNL+-%eV0Ax%d*DyV9Q__DGr|PX zAVU}xO~_Ey{766%ra!uiw6>O4_|JY9=hzP^df?+V@1yeLe~h*BJ;B#V^pHJue0~bx z8u4W}TM~tIM-V6fj_k9a#~nP2%7=+X4`$XHl}w@2!~RJlxpRnD{};LXf5gbEvRK`*;1!*dc!xaS{|CP+MpT`|IlRtk#=j#eu z2<`o4bkn_nfzBs3=cBsXY+|H&A4zxV6@T{jaRO`mzM>Vtp^ZE85y9ewgi;|GsM(1V zyD?vtD`u$fSv(iu2@vs3Sl2#;h}NPJKEH!NyBVA}e~dozcNlIr=7n$JJo}fpU2UK| zAM_{>r~f>1_;j9_)^lC-6WhTO_3xp>YF(D&X0oS_&(J<@67&_T`xAzNx$)+r3u~?+ zp#&JFoU!J+(MI)@ZQD!F4(j9?|0sDUov$wvpmXHT?#F%Y3&`B1JoTH!=zaqCna|=} zcm=#HUiX`*{eO)}9naST%{}Y`jThcVcm3_8z2ymoec{Z4_-9H$NjXC_;A4Trb5E4) z3MBZ|cNb&Z$kyEHpFq7_#E?p$j(!Q}%nN=)seEeJd+Bo+nUhnV!><(=L(k#;+%M$iY*qtKV%))yfD7jbA?A1j6ZX&0rqjUw(K%Z4lf9u0& zS(mp9OFJ{;K3^sd;XeCkc+Y$mIru_;SC1~@IKc2SEUfYuoXAdkTRy<3x^fMgrlNkc zp>gM(x!yvxzfdwnUG^m-wq`m%DQgt6hV=W6WAg1Kr zmiA5>CCf-O{S0R!JIO9{cUE_x&)+S)So1a)B`DICJ}}luh!{Pq-$%Oo-FU+C6F5sB z6U?hi>70y>h%;9IGqg9{Ms|tIz5^AYuX90L#TTLknIroHBLi71MCw)Lbgg|Dr}A!; zT=rAu7t_P!-A0U5^G9fJ+{dVn@Y6I(Q39v!DH6|4Z%Qp^ij#Y(q+{(z$<^ME7VoSB z7^R-vAgW~*qs>3hnYw!zm2rL=hcFC3jGQGryj%(7Y-CBFsNiJNhe$Pl3?(byF%zPM zKnYN03uCK)ku!C7k&sb-n#b(zX{U1pvlfzRAZeCys^Q)At@<@wbJbOA@I~R0z>8nc z=#Jm#Wc6)iWSD;o!)j=mr4dD*Bgliok}C<*gg9Tbhpw&v5vOt=aCNx^jhC(Nv*Mzlw->jezrRLTnNFnI3TS%?`7)_Bi#QT4O zbUO0C(O0aHQUiuI&=}-m*D%=nVLHk-`$+#PIpR=jHPJD28V|JbrhK>5#R5Q*_`U~7 zK+&3m@s1*c(((?;Cmiq*8pF=Qk>{X03+)r=)9)^i7 zYf1M)huOSt(VIbzM+P$~0nD>Y7=R~C`peca9BZX!>=x?#Um%)1gmn9uiK8D+IWy4_ z?6TiZ=@dE>XOK5`cvcgcnmg&Ny@dh04#m}aHt^hzky%*pk*0OYzuDPO>{-J zGicZ0imRKe5Qaf`&jY0Y^-EVo2{MhV{gcex9OmXd6Ez2mHfyf5=`P#EKzuE=&G%xC z^--NZO=zeMnYjqwAetOn2n>}6Yx%PY#RMMp5JI4kNS#mfY6B&0JhKWSt8mJ;GFHBc zp-2k}87HUSIj4b}4Xr*ppTY);a1~~K^O7q;WXBDJx9;|x_>>m-;wSqLE}6G9B}Am6 z(jB2j4dV42#Y%T$IK2pG7`z0A%1)dBfG`n+QDz8jR-z(na6)w?BCBxXjik&tBRY(S x@eVq^x-b$Ld-}1-HgRT@vY-9*6+JcN{{w+|_%Vy--E;r|002ovPDHLkV1kUNj;sIx diff --git a/lnbits/extensions/scrub/static/js/index.js b/lnbits/extensions/scrub/static/js/index.js deleted file mode 100644 index 439907921..000000000 --- a/lnbits/extensions/scrub/static/js/index.js +++ /dev/null @@ -1,143 +0,0 @@ -/* globals Quasar, Vue, _, VueQrcode, windowMixin, LNbits, LOCALE */ - -Vue.component(VueQrcode.name, VueQrcode) - -var locationPath = [ - window.location.protocol, - '//', - window.location.host, - window.location.pathname -].join('') - -var mapScrubLink = obj => { - obj._data = _.clone(obj) - obj.date = Quasar.utils.date.formatDate( - new Date(obj.time * 1000), - 'YYYY-MM-DD HH:mm' - ) - obj.amount = new Intl.NumberFormat(LOCALE).format(obj.amount) - obj.print_url = [locationPath, 'print/', obj.id].join('') - obj.pay_url = [locationPath, obj.id].join('') - return obj -} - -new Vue({ - el: '#vue', - mixins: [windowMixin], - data() { - return { - checker: null, - payLinks: [], - payLinksTable: { - pagination: { - rowsPerPage: 10 - } - }, - formDialog: { - show: false, - data: {} - }, - qrCodeDialog: { - show: false, - data: null - } - } - }, - methods: { - getScrubLinks() { - LNbits.api - .request( - 'GET', - '/scrub/api/v1/links?all_wallets=true', - this.g.user.wallets[0].inkey - ) - .then(response => { - this.payLinks = response.data.map(mapScrubLink) - }) - .catch(err => { - clearInterval(this.checker) - LNbits.utils.notifyApiError(err) - }) - }, - closeFormDialog() { - this.resetFormData() - }, - openUpdateDialog(linkId) { - const link = _.findWhere(this.payLinks, {id: linkId}) - - this.formDialog.data = _.clone(link._data) - this.formDialog.show = true - }, - sendFormData() { - const wallet = _.findWhere(this.g.user.wallets, { - id: this.formDialog.data.wallet - }) - let data = Object.freeze(this.formDialog.data) - console.log(wallet, data) - - if (data.id) { - this.updateScrubLink(wallet, data) - } else { - this.createScrubLink(wallet, data) - } - }, - resetFormData() { - this.formDialog = { - show: false, - data: {} - } - }, - updateScrubLink(wallet, data) { - LNbits.api - .request('PUT', '/scrub/api/v1/links/' + data.id, wallet.adminkey, data) - .then(response => { - this.payLinks = _.reject(this.payLinks, obj => obj.id === data.id) - this.payLinks.push(mapScrubLink(response.data)) - this.formDialog.show = false - this.resetFormData() - }) - .catch(err => { - LNbits.utils.notifyApiError(err) - }) - }, - createScrubLink(wallet, data) { - LNbits.api - .request('POST', '/scrub/api/v1/links', wallet.adminkey, data) - .then(response => { - console.log('RES', response) - this.getScrubLinks() - this.formDialog.show = false - this.resetFormData() - }) - .catch(err => { - LNbits.utils.notifyApiError(err) - }) - }, - deleteScrubLink(linkId) { - var link = _.findWhere(this.payLinks, {id: linkId}) - - LNbits.utils - .confirmDialog('Are you sure you want to delete this pay link?') - .onOk(() => { - LNbits.api - .request( - 'DELETE', - '/scrub/api/v1/links/' + linkId, - _.findWhere(this.g.user.wallets, {id: link.wallet}).adminkey - ) - .then(response => { - this.payLinks = _.reject(this.payLinks, obj => obj.id === linkId) - }) - .catch(err => { - LNbits.utils.notifyApiError(err) - }) - }) - } - }, - created() { - if (this.g.user.wallets.length) { - var getScrubLinks = this.getScrubLinks - getScrubLinks() - } - } -}) diff --git a/lnbits/extensions/scrub/tasks.py b/lnbits/extensions/scrub/tasks.py deleted file mode 100644 index 26249bb1b..000000000 --- a/lnbits/extensions/scrub/tasks.py +++ /dev/null @@ -1,89 +0,0 @@ -import asyncio -import json -from http import HTTPStatus -from math import floor -from urllib.parse import urlparse - -import httpx -from fastapi import HTTPException - -from lnbits import bolt11 -from lnbits.core.models import Payment -from lnbits.core.services import pay_invoice -from lnbits.helpers import get_current_extension_name -from lnbits.tasks import register_invoice_listener - -from .crud import get_scrub_by_wallet - - -async def wait_for_paid_invoices(): - invoice_queue = asyncio.Queue() - register_invoice_listener(invoice_queue, get_current_extension_name()) - - while True: - payment = await invoice_queue.get() - await on_invoice_paid(payment) - - -async def on_invoice_paid(payment: Payment): - # (avoid loops) - if payment.extra.get("tag") == "scrubed": - # already scrubbed - return - - scrub_link = await get_scrub_by_wallet(payment.wallet_id) - - if not scrub_link: - return - - from lnbits.core.views.api import api_lnurlscan - - # DECODE LNURLP OR LNADDRESS - data = await api_lnurlscan(scrub_link.payoraddress) - - # I REALLY HATE THIS DUPLICATION OF CODE!! CORE/VIEWS/API.PY, LINE 267 - domain = urlparse(data["callback"]).netloc - rounded_amount = floor(payment.amount / 1000) * 1000 - - async with httpx.AsyncClient() as client: - try: - r = await client.get( - data["callback"], - params={"amount": rounded_amount}, - timeout=40, - ) - if r.is_error: - raise httpx.ConnectError("issue with scrub callback") - except (httpx.ConnectError, httpx.RequestError): - raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, - detail=f"Failed to connect to {domain}.", - ) - - params = json.loads(r.text) - if params.get("status") == "ERROR": - raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, - detail=f"{domain} said: '{params.get('reason', '')}'", - ) - - invoice = bolt11.decode(params["pr"]) - - if invoice.amount_msat != rounded_amount: - raise HTTPException( - status_code=HTTPStatus.BAD_REQUEST, - detail=f"{domain} returned an invalid invoice. Expected {payment.amount} msat, got {invoice.amount_msat}.", - ) - - payment_hash = await pay_invoice( - wallet_id=payment.wallet_id, - payment_request=params["pr"], - description=data["description"], - extra={"tag": "scrubed"}, - ) - - return { - "payment_hash": payment_hash, - # maintain backwards compatibility with API clients: - "checking_id": payment_hash, - } diff --git a/lnbits/extensions/scrub/templates/scrub/_api_docs.html b/lnbits/extensions/scrub/templates/scrub/_api_docs.html deleted file mode 100644 index ae3f44d88..000000000 --- a/lnbits/extensions/scrub/templates/scrub/_api_docs.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - GET /scrub/api/v1/links -
Headers
- {"X-Api-Key": <invoice_key>}
-
Body (application/json)
-
- Returns 200 OK (application/json) -
- [<pay_link_object>, ...] -
Curl example
- curl -X GET {{ request.base_url }}scrub/api/v1/links?all_wallets=true - -H "X-Api-Key: {{ user.wallets[0].inkey }}" - -
-
-
- - - - GET - /scrub/api/v1/links/<scrub_id> -
Headers
- {"X-Api-Key": <invoice_key>}
-
Body (application/json)
-
- Returns 200 OK (application/json) -
- {"id": <string>, "wallet": <string>, "description": - <string>, "payoraddress": <string>} -
Curl example
- curl -X GET {{ request.base_url }}scrub/api/v1/links/<pay_id> - -H "X-Api-Key: {{ user.wallets[0].inkey }}" - -
-
-
- - - - POST /scrub/api/v1/links -
Headers
- {"X-Api-Key": <admin_key>}
-
Body (application/json)
- {"wallet": <string>, "description": <string>, - "payoraddress": <string>} -
- Returns 201 CREATED (application/json) -
- {"id": <string>, "wallet": <string>, "description": - <string>, "payoraddress": <string>} -
Curl example
- curl -X POST {{ request.base_url }}scrub/api/v1/links -d '{"wallet": - <string>, "description": <string>, "payoraddress": - <string>}' -H "Content-type: application/json" -H "X-Api-Key: {{ - user.wallets[0].adminkey }}" - -
-
-
- - - - PUT - /scrub/api/v1/links/<pay_id> -
Headers
- {"X-Api-Key": <admin_key>}
-
Body (application/json)
- {"wallet": <string>, "description": <string>, - "payoraddress": <string>} -
- Returns 200 OK (application/json) -
- {"id": <string>, "wallet": <string>, "description": - <string>, "payoraddress": <string>} -
Curl example
- curl -X PUT {{ request.base_url }}scrub/api/v1/links/<pay_id> - -d '{"wallet": <string>, "description": <string>, - "payoraddress": <string>}' -H "Content-type: application/json" - -H "X-Api-Key: {{ user.wallets[0].adminkey }}" - -
-
-
- - - - DELETE - /scrub/api/v1/links/<pay_id> -
Headers
- {"X-Api-Key": <admin_key>}
-
Returns 204 NO CONTENT
- -
Curl example
- curl -X DELETE {{ request.base_url - }}scrub/api/v1/links/<pay_id> -H "X-Api-Key: {{ - user.wallets[0].adminkey }}" - -
-
-
-
diff --git a/lnbits/extensions/scrub/templates/scrub/_lnurl.html b/lnbits/extensions/scrub/templates/scrub/_lnurl.html deleted file mode 100644 index f2ba86611..000000000 --- a/lnbits/extensions/scrub/templates/scrub/_lnurl.html +++ /dev/null @@ -1,31 +0,0 @@ - - - -

- WARNING: LNURL must be used over https or TOR
- LNURL is a range of lightning-network standards that allow us to use - lightning-network differently. An LNURL-pay is a link that wallets use - to fetch an invoice from a server on-demand. The link or QR code is - fixed, but each time it is read by a compatible wallet a new QR code is - issued by the service. It can be used to activate machines without them - having to maintain an electronic screen to generate and show invoices - locally, or to sell any predefined good or service automatically. -

-

- Exploring LNURL and finding use cases, is really helping inform - lightning protocol development, rather than the protocol dictating how - lightning-network should be engaged with. -

- Check - Awesome LNURL - for further information. -
-
-
diff --git a/lnbits/extensions/scrub/templates/scrub/index.html b/lnbits/extensions/scrub/templates/scrub/index.html deleted file mode 100644 index a3756df35..000000000 --- a/lnbits/extensions/scrub/templates/scrub/index.html +++ /dev/null @@ -1,156 +0,0 @@ -{% extends "base.html" %} {% from "macros.jinja" import window_vars with context -%} {% block page %} -
-
- - - New scrub link - - - - - -
-
-
Scrub links
-
-
- - {% raw %} - - - {% endraw %} - -
-
-
- -
- - -
{{SITE_TITLE}} Scrub extension
-

- Automatically forward funds (Scrub) that get paid to the LNbits - wallet, to an LNURLpay or Lightning Address. -
- More info in Scrub's - readme. -

-

- Important: wallet will need a float to account for - any fees, before being able to push a payment -

-
- - - - {% include "scrub/_api_docs.html" %} - - {% include "scrub/_lnurl.html" %} - - -
-
- - - - - - - - - -
- Update pay link - Create pay link - Cancel -
-
-
-
-
-{% endblock %} {% block scripts %} {{ window_vars(user) }} - -{% endblock %} diff --git a/lnbits/extensions/scrub/views.py b/lnbits/extensions/scrub/views.py deleted file mode 100644 index 489580133..000000000 --- a/lnbits/extensions/scrub/views.py +++ /dev/null @@ -1,17 +0,0 @@ -from fastapi import Depends, Request -from fastapi.templating import Jinja2Templates -from starlette.responses import HTMLResponse - -from lnbits.core.models import User -from lnbits.decorators import check_user_exists - -from . import scrub_ext, scrub_renderer - -templates = Jinja2Templates(directory="templates") - - -@scrub_ext.get("/", response_class=HTMLResponse) -async def index(request: Request, user: User = Depends(check_user_exists)): - return scrub_renderer().TemplateResponse( - "scrub/index.html", {"request": request, "user": user.dict()} - ) diff --git a/lnbits/extensions/scrub/views_api.py b/lnbits/extensions/scrub/views_api.py deleted file mode 100644 index eae0098d9..000000000 --- a/lnbits/extensions/scrub/views_api.py +++ /dev/null @@ -1,107 +0,0 @@ -from http import HTTPStatus - -from fastapi import Depends, Query -from starlette.exceptions import HTTPException - -from lnbits.core.crud import get_user -from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key - -from . import scrub_ext -from .crud import ( - create_scrub_link, - delete_scrub_link, - get_scrub_link, - get_scrub_links, - unique_scrubed_wallet, - update_scrub_link, -) -from .models import CreateScrubLink - - -@scrub_ext.get("/api/v1/links", status_code=HTTPStatus.OK) -async def api_links( - wallet: WalletTypeInfo = Depends(get_key_type), - all_wallets: bool = Query(False), -): - wallet_ids = [wallet.wallet.id] - - if all_wallets: - user = await get_user(wallet.wallet.user) - wallet_ids = user.wallet_ids if user else [] - - try: - return [link.dict() for link in await get_scrub_links(wallet_ids)] - - except: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, - detail="No SCRUB links made yet", - ) - - -@scrub_ext.get("/api/v1/links/{link_id}", status_code=HTTPStatus.OK) -async def api_link_retrieve(link_id, wallet: WalletTypeInfo = Depends(get_key_type)): - link = await get_scrub_link(link_id) - - if not link: - raise HTTPException( - detail="Scrub link does not exist.", status_code=HTTPStatus.NOT_FOUND - ) - - if link.wallet != wallet.wallet.id: - raise HTTPException( - detail="Not your pay link.", status_code=HTTPStatus.FORBIDDEN - ) - - return link - - -@scrub_ext.post("/api/v1/links", status_code=HTTPStatus.CREATED) -@scrub_ext.put("/api/v1/links/{link_id}", status_code=HTTPStatus.OK) -async def api_scrub_create_or_update( - data: CreateScrubLink, - link_id=None, - wallet: WalletTypeInfo = Depends(require_admin_key), -): - if link_id: - link = await get_scrub_link(link_id) - - if not link: - raise HTTPException( - detail="Scrub link does not exist.", status_code=HTTPStatus.NOT_FOUND - ) - - if link.wallet != wallet.wallet.id: - raise HTTPException( - detail="Not your pay link.", status_code=HTTPStatus.FORBIDDEN - ) - - link = await update_scrub_link(**data.dict(), link_id=link_id) - else: - wallet_has_scrub = await unique_scrubed_wallet(wallet_id=data.wallet) - if wallet_has_scrub > 0: - raise HTTPException( - detail="Wallet is already being Scrubbed", - status_code=HTTPStatus.FORBIDDEN, - ) - link = await create_scrub_link(data=data) - - return link - - -@scrub_ext.delete("/api/v1/links/{link_id}") -async def api_link_delete(link_id, wallet: WalletTypeInfo = Depends(require_admin_key)): - link = await get_scrub_link(link_id) - - if not link: - raise HTTPException( - detail="Scrub link does not exist.", status_code=HTTPStatus.NOT_FOUND - ) - - if link.wallet != wallet.wallet.id: - raise HTTPException( - detail="Not your pay link.", status_code=HTTPStatus.FORBIDDEN - ) - - await delete_scrub_link(link_id) - return "", HTTPStatus.NO_CONTENT