mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-24 06:48:02 +01:00
Merge pull request #1361 from lnbits/tinyurl
Adds universal tinyurl redirect for lnurls and the like
This commit is contained in:
commit
0de2a62159
4 changed files with 147 additions and 2 deletions
|
@ -4,12 +4,14 @@ from typing import Any, Dict, List, Optional
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
|
import shortuuid
|
||||||
|
|
||||||
from lnbits import bolt11
|
from lnbits import bolt11
|
||||||
from lnbits.db import COCKROACH, POSTGRES, Connection
|
from lnbits.db import COCKROACH, POSTGRES, Connection
|
||||||
from lnbits.settings import AdminSettings, EditableSettings, SuperSettings, settings
|
from lnbits.settings import AdminSettings, EditableSettings, SuperSettings, settings
|
||||||
|
|
||||||
from . import db
|
from . import db
|
||||||
from .models import BalanceCheck, Payment, User, Wallet
|
from .models import BalanceCheck, Payment, TinyURL, User, Wallet
|
||||||
|
|
||||||
# accounts
|
# accounts
|
||||||
# --------
|
# --------
|
||||||
|
@ -620,3 +622,44 @@ async def create_admin_settings(super_user: str, new_settings: dict):
|
||||||
sql = f"INSERT INTO settings (super_user, editable_settings) VALUES (?, ?)"
|
sql = f"INSERT INTO settings (super_user, editable_settings) VALUES (?, ?)"
|
||||||
await db.execute(sql, (super_user, json.dumps(new_settings)))
|
await db.execute(sql, (super_user, json.dumps(new_settings)))
|
||||||
return await get_super_settings()
|
return await get_super_settings()
|
||||||
|
|
||||||
|
|
||||||
|
# tinyurl
|
||||||
|
# -------
|
||||||
|
|
||||||
|
|
||||||
|
async def create_tinyurl(domain: str, endless: bool, wallet: str):
|
||||||
|
tinyurl_id = shortuuid.uuid()[:8]
|
||||||
|
await db.execute(
|
||||||
|
f"INSERT INTO tiny_url (id, url, endless, wallet) VALUES (?, ?, ?, ?)",
|
||||||
|
(
|
||||||
|
tinyurl_id,
|
||||||
|
domain,
|
||||||
|
endless,
|
||||||
|
wallet,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return await get_tinyurl(tinyurl_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def get_tinyurl(tinyurl_id: str) -> Optional[TinyURL]:
|
||||||
|
row = await db.fetchone(
|
||||||
|
f"SELECT * FROM tiny_url WHERE id = ?",
|
||||||
|
(tinyurl_id,),
|
||||||
|
)
|
||||||
|
return TinyURL.from_row(row) if row else None
|
||||||
|
|
||||||
|
|
||||||
|
async def get_tinyurl_by_url(url: str) -> List[TinyURL]:
|
||||||
|
rows = await db.fetchall(
|
||||||
|
f"SELECT * FROM tiny_url WHERE url = ?",
|
||||||
|
(url,),
|
||||||
|
)
|
||||||
|
return [TinyURL.from_row(row) for row in rows]
|
||||||
|
|
||||||
|
|
||||||
|
async def delete_tinyurl(tinyurl_id: str):
|
||||||
|
row = await db.execute(
|
||||||
|
f"DELETE FROM tiny_url WHERE id = ?",
|
||||||
|
(tinyurl_id,),
|
||||||
|
)
|
||||||
|
|
|
@ -269,3 +269,17 @@ async def m008_create_admin_settings_table(db):
|
||||||
);
|
);
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def m009_create_tinyurl_table(db):
|
||||||
|
await db.execute(
|
||||||
|
f"""
|
||||||
|
CREATE TABLE IF NOT EXISTS tiny_url (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
url TEXT,
|
||||||
|
endless BOOL NOT NULL DEFAULT false,
|
||||||
|
wallet TEXT,
|
||||||
|
time TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}
|
||||||
|
);
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
|
@ -213,3 +213,15 @@ class BalanceCheck(BaseModel):
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row(cls, row: Row):
|
def from_row(cls, row: Row):
|
||||||
return cls(wallet=row["wallet"], service=row["service"], url=row["url"])
|
return cls(wallet=row["wallet"], service=row["service"], url=row["url"])
|
||||||
|
|
||||||
|
|
||||||
|
class TinyURL(BaseModel):
|
||||||
|
id: str
|
||||||
|
url: str
|
||||||
|
endless: bool
|
||||||
|
wallet: str
|
||||||
|
time: float
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_row(cls, row: Row):
|
||||||
|
return cls(**dict(row))
|
||||||
|
|
|
@ -26,7 +26,7 @@ from loguru import logger
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from pydantic.fields import Field
|
from pydantic.fields import Field
|
||||||
from sse_starlette.sse import EventSourceResponse
|
from sse_starlette.sse import EventSourceResponse
|
||||||
from starlette.responses import StreamingResponse
|
from starlette.responses import RedirectResponse, StreamingResponse
|
||||||
|
|
||||||
from lnbits import bolt11, lnurl
|
from lnbits import bolt11, lnurl
|
||||||
from lnbits.core.models import Payment, Wallet
|
from lnbits.core.models import Payment, Wallet
|
||||||
|
@ -47,8 +47,12 @@ from lnbits.utils.exchange_rates import (
|
||||||
|
|
||||||
from .. import core_app, db
|
from .. import core_app, db
|
||||||
from ..crud import (
|
from ..crud import (
|
||||||
|
create_tinyurl,
|
||||||
|
delete_tinyurl,
|
||||||
get_payments,
|
get_payments,
|
||||||
get_standalone_payment,
|
get_standalone_payment,
|
||||||
|
get_tinyurl,
|
||||||
|
get_tinyurl_by_url,
|
||||||
get_total_balance,
|
get_total_balance,
|
||||||
get_wallet_for_key,
|
get_wallet_for_key,
|
||||||
save_balance_check,
|
save_balance_check,
|
||||||
|
@ -706,3 +710,75 @@ async def websocket_update_get(item_id: str, data: str):
|
||||||
return {"sent": True, "data": data}
|
return {"sent": True, "data": data}
|
||||||
except:
|
except:
|
||||||
return {"sent": False, "data": data}
|
return {"sent": False, "data": data}
|
||||||
|
|
||||||
|
|
||||||
|
############################TINYURL##################################
|
||||||
|
|
||||||
|
|
||||||
|
@core_app.post("/api/v1/tinyurl")
|
||||||
|
async def api_create_tinyurl(
|
||||||
|
url: str, endless: bool = False, wallet: WalletTypeInfo = Depends(get_key_type)
|
||||||
|
):
|
||||||
|
tinyurls = await get_tinyurl_by_url(url)
|
||||||
|
try:
|
||||||
|
for tinyurl in tinyurls:
|
||||||
|
if tinyurl:
|
||||||
|
if tinyurl.wallet == wallet.wallet.inkey:
|
||||||
|
return tinyurl
|
||||||
|
return await create_tinyurl(url, endless, wallet.wallet.inkey)
|
||||||
|
except:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.BAD_REQUEST, detail="Unable to create tinyurl"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@core_app.get("/api/v1/tinyurl/{tinyurl_id}")
|
||||||
|
async def api_get_tinyurl(
|
||||||
|
tinyurl_id: str, wallet: WalletTypeInfo = Depends(get_key_type)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
tinyurl = await get_tinyurl(tinyurl_id)
|
||||||
|
if tinyurl:
|
||||||
|
if tinyurl.wallet == wallet.wallet.inkey:
|
||||||
|
return tinyurl
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.FORBIDDEN, detail="Wrong key provided."
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.NOT_FOUND, detail="Unable to fetch tinyurl"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@core_app.delete("/api/v1/tinyurl/{tinyurl_id}")
|
||||||
|
async def api_delete_tinyurl(
|
||||||
|
tinyurl_id: str, wallet: WalletTypeInfo = Depends(get_key_type)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
tinyurl = await get_tinyurl(tinyurl_id)
|
||||||
|
if tinyurl:
|
||||||
|
if tinyurl.wallet == wallet.wallet.inkey:
|
||||||
|
await delete_tinyurl(tinyurl_id)
|
||||||
|
return {"deleted": True}
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.FORBIDDEN, detail="Wrong key provided."
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.BAD_REQUEST, detail="Unable to delete"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@core_app.get("/t/{tinyurl_id}")
|
||||||
|
async def api_tinyurl(tinyurl_id: str):
|
||||||
|
try:
|
||||||
|
tinyurl = await get_tinyurl(tinyurl_id)
|
||||||
|
if tinyurl:
|
||||||
|
response = RedirectResponse(url=tinyurl.url)
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
except:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=HTTPStatus.NOT_FOUND, detail="unable to find tinyurl"
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue