Skip to content

Commit

Permalink
fix ups
Browse files Browse the repository at this point in the history
  • Loading branch information
talvasconcelos committed Oct 3, 2024
1 parent 1b9522a commit e7138dd
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 17 deletions.
12 changes: 9 additions & 3 deletions crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@

async def create_schedule(wallet_id: str, data: CreateSchedule) -> Schedule:
schedule_id = urlsafe_short_hash()
# hardcode timeslot for now
timeslot = 30

schedule = Schedule(
id=schedule_id,
wallet=wallet_id,
Expand All @@ -29,7 +28,8 @@ async def create_schedule(wallet_id: str, data: CreateSchedule) -> Schedule:
start_time=data.start_time,
end_time=data.end_time,
amount=data.amount,
timeslot=timeslot,
timeslot=data.timeslot,
currency=data.currency,
)
await db.execute(
insert_query("lncalendar.schedule", schedule),
Expand Down Expand Up @@ -92,6 +92,12 @@ async def create_appointment(
)
return appointment

async def update_appointment(appointment: Appointment) -> Appointment:
await db.execute(
update_query("lncalendar.appointment", appointment),
appointment.dict(),
)
return appointment

async def get_appointment(appointment_id: str) -> Optional[Appointment]:
row = await db.fetchone(
Expand Down
48 changes: 42 additions & 6 deletions migrations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
from sqlalchemy.exc import OperationalError

from lnbits.helpers import insert_query


async def m001_initial(db):
"""
Initial schedules table.
Expand Down Expand Up @@ -70,8 +75,6 @@ async def m002_rename_time_to_created_at(db):
"""
)


async def m003_add_unavailable_name(db):
"""
Add name to the unavailable table.
"""
Expand All @@ -82,8 +85,6 @@ async def m003_add_unavailable_name(db):
"""
)


async def m004_add_timeslot(db):
"""
Add timeslot to the schedule table.
"""
Expand All @@ -94,8 +95,6 @@ async def m004_add_timeslot(db):
"""
)


async def m005_add_nostr_pubkey(db):
"""
Add nostr_pubkey to the appointment table.
"""
Expand All @@ -105,3 +104,40 @@ async def m005_add_nostr_pubkey(db):
ADD COLUMN nostr_pubkey TEXT;
"""
)


async def m003_add_fiat_currency(db):
"""
Add currency to schedule to allow fiat denomination
of appointments. Make price a float.
"""
try:
await db.execute(
"ALTER TABLE lncalendar.schedule RENAME TO schedule_backup;")
await db.execute(
"""
CREATE TABLE lncalendar.schedule (
id TEXT PRIMARY KEY,
wallet TEXT NOT NULL,
name TEXT NOT NULL,
start_day INTEGER NOT NULL,
end_day INTEGER NOT NULL,
start_time TEXT NOT NULL,
end_time TEXT NOT NULL,
amount FLOAT NOT NULL,
timeslot INTEGER NOT NULL DEFAULT 30,
currency TEXT NOT NULL DEFAULT 'sat'
);
"""
)

await db.execute(
"""
INSERT INTO lncalendar.schedule (id, wallet, name, start_day, end_day, start_time, end_time, amount, timeslot)
SELECT id, wallet, name, start_day, end_day, start_time, end_time, amount, timeslot FROM lncalendar.schedule_backup;
"""
)

await db.execute("DROP TABLE lncalendar.schedule_backup;")
except OperationalError:
pass
17 changes: 14 additions & 3 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ class CreateSchedule(BaseModel):
end_day: int = Query(..., ge=0, le=6)
start_time: str = Query(...)
end_time: str = Query(...)
amount: int = Query(..., ge=1)
timeslot: int = Query(..., ge=15)
amount: float = Query(..., ge=0)
timeslot: int = Query(30, ge=5)
currency: str = Query('sat')


class CreateUnavailableTime(BaseModel):
Expand All @@ -32,6 +33,15 @@ class CreateAppointment(BaseModel):
end_time: str = Query(...)
schedule: str = Query(...)

class UpdateAppointment(BaseModel):
name: Optional[str] = Query(None)
email: Optional[str] = Query(None)
nostr_pubkey: Optional[str] = Query(None)
info: Optional[str] = Query(None)
start_time: Optional[str] = Query(None)
end_time: Optional[str] = Query(None)
schedule: Optional[str] = Query(None)


class Schedule(BaseModel):
id: str
Expand All @@ -41,8 +51,9 @@ class Schedule(BaseModel):
end_day: int
start_time: str
end_time: str
amount: int
amount: float
timeslot: int
currency: str

@property
def availabe_days(self):
Expand Down
12 changes: 11 additions & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from lnbits.core.models import Payment
from lnbits.helpers import get_current_extension_name
from lnbits.tasks import register_invoice_listener
from lnbits.utils.exchange_rates import fiat_amount_as_satoshis

from .crud import get_appointment, get_schedule, set_appointment_paid

Expand All @@ -30,5 +31,14 @@ async def on_invoice_paid(payment: Payment) -> None:
schedule = await get_schedule(appointment.schedule)
assert schedule

if payment.amount == schedule.amount * 1000:
price = (
schedule.amount * 1000
if schedule.currency == "sat"
else await fiat_amount_as_satoshis(schedule.amount, schedule.currency)
* 1000
)

lower_bound = price * 0.99 # 1% decrease

if abs(payment.amount) >= lower_bound: # allow 1% error
await set_appointment_paid(payment.payment_hash)
54 changes: 50 additions & 4 deletions views_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

from fastapi import APIRouter, Depends, Query
from fastapi.exceptions import HTTPException
from httpx import delete

from lnbits import app
from lnbits.core.crud import get_standalone_payment, get_user
from lnbits.core.models import User, WalletTypeInfo
from lnbits.core.services import create_invoice
from lnbits.decorators import check_user_exists, require_admin_key, require_invoice_key
from lnbits.utils.exchange_rates import (
allowed_currencies,
fiat_amount_as_satoshis,
get_fiat_rate_satoshis,
satoshis_amount_as_fiat,
)

from .crud import (
create_appointment,
Expand All @@ -25,9 +29,15 @@
get_unavailable_times,
purge_appointments,
set_appointment_paid,
update_appointment,
update_schedule,
)
from .models import CreateAppointment, CreateSchedule, CreateUnavailableTime
from .models import (
CreateAppointment,
CreateSchedule,
CreateUnavailableTime,
UpdateAppointment,
)

lncalendar_api_router = APIRouter()

Expand Down Expand Up @@ -129,9 +139,12 @@ async def api_appointment_create(data: CreateAppointment):
status_code=HTTPStatus.NOT_FOUND, detail="Schedule does not exist."
)
try:
amount = schedule.amount
if schedule.currency != "sat":
amount = await fiat_amount_as_satoshis(schedule.amount, schedule.currency)
payment_hash, payment_request = await create_invoice(
wallet_id=schedule.wallet,
amount=schedule.amount, # type: ignore
amount=amount, # type: ignore
memo=f"{schedule.name}",
extra={"tag": "lncalendar", "name": data.name, "email": data.email},
)
Expand All @@ -145,6 +158,34 @@ async def api_appointment_create(data: CreateAppointment):
return {"payment_hash": payment_hash, "payment_request": payment_request}


@lncalendar_api_router.put("/api/v1/appointment/{appointment_id}")
async def api_appointment_update(
appointment_id: str,
data: UpdateAppointment,
user: User = Depends(check_user_exists),
):
appointment = await get_appointment(appointment_id)
if not appointment:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Appointment does not exist."
)
schedule = await get_schedule(appointment.schedule)
if not schedule:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Schedule does not exist."
)
if schedule.wallet not in user.wallet_ids:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not your schedule."
)

for k, v in data.dict().items():
if v is not None:
setattr(appointment, k, v)

appointment = await update_appointment(appointment)
return appointment.dict()

@lncalendar_api_router.get("/api/v1/appointment/purge/{schedule_id}")
async def api_purge_appointments(schedule_id: str):
schedule = await get_schedule(schedule_id)
Expand Down Expand Up @@ -258,3 +299,8 @@ async def api_unavailable_delete(
)
await delete_unavailable_time(unavailable_id)
return "", HTTPStatus.NO_CONTENT

## Currency API
@lncalendar_api_router.get("/api/v1/currencies")
async def api_get_currencies():
return allowed_currencies()

0 comments on commit e7138dd

Please sign in to comment.