Changed naming to Market and Stall

This commit is contained in:
ben
2023-01-04 21:08:28 +00:00
parent 4a86acf879
commit a5727a0c92
22 changed files with 409 additions and 409 deletions

View File

@@ -1,7 +1,7 @@
<h1>Shop</h1>
<h1>Market</h1>
<h2>A movable market stand</h2>
Make a list of products to sell, point the list to an relay (or many), stack sats.
Shop is a movable market stand, for anon transactions. You then give permission for an relay to list those products. Delivery addresses are sent through the Lightning Network.
Market is a movable market stand, for anon transactions. You then give permission for an relay to list those products. Delivery addresses are sent through the Lightning Network.
<img src="https://i.imgur.com/P1tvBSG.png">
<h2>API endpoints</h2>

View File

@@ -7,20 +7,20 @@ from lnbits.db import Database
from lnbits.helpers import template_renderer
from lnbits.tasks import catch_everything_and_restart
db = Database("ext_shop")
db = Database("ext_market")
shop_ext: APIRouter = APIRouter(prefix="/shop", tags=["shop"])
market_ext: APIRouter = APIRouter(prefix="/market", tags=["market"])
shop_static_files = [
market_static_files = [
{
"path": "/shop/static",
"app": StaticFiles(directory="lnbits/extensions/shop/static"),
"name": "shop_static",
"path": "/market/static",
"app": StaticFiles(directory="lnbits/extensions/market/static"),
"name": "market_static",
}
]
# if 'nostradmin' not in LNBITS_ADMIN_EXTENSIONS:
# @shop_ext.get("/", response_class=HTMLResponse)
# @market_ext.get("/", response_class=HTMLResponse)
# async def index(request: Request):
# return template_renderer().TemplateResponse(
# "error.html", {"request": request, "err": "Ask system admin to enable NostrAdmin!"}
@@ -28,9 +28,9 @@ shop_static_files = [
# else:
def shop_renderer():
return template_renderer(["lnbits/extensions/shop/templates"])
# return template_renderer(["lnbits/extensions/shop/templates"])
def market_renderer():
return template_renderer(["lnbits/extensions/market/templates"])
# return template_renderer(["lnbits/extensions/market/templates"])
from .tasks import wait_for_paid_invoices
@@ -38,6 +38,6 @@ from .views import * # noqa
from .views_api import * # noqa
def shop_start():
def market_start():
loop = asyncio.get_event_loop()
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))

View File

@@ -0,0 +1,6 @@
{
"name": "Market",
"short_description": "Webmarket on LNbits",
"tile": "/market/static/images/bitcoin-shop.png",
"contributors": ["benarc", "talvasconcelos"]
}

View File

@@ -17,7 +17,7 @@ from .models import (
OrderDetail,
Orders,
Products,
ShopSettings,
MarketSettings,
Stalls,
Zones,
createOrder,
@@ -30,11 +30,11 @@ from .models import (
###Products
async def create_shop_product(data: createProduct) -> Products:
async def create_market_product(data: createProduct) -> Products:
product_id = urlsafe_short_hash()
await db.execute(
f"""
INSERT INTO shop.products (id, stall, product, categories, description, image, price, quantity)
INSERT INTO market.products (id, stall, product, categories, description, image, price, quantity)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""",
(
@@ -48,55 +48,55 @@ async def create_shop_product(data: createProduct) -> Products:
data.quantity,
),
)
product = await get_shop_product(product_id)
product = await get_market_product(product_id)
assert product, "Newly created product couldn't be retrieved"
return product
async def update_shop_product(product_id: str, **kwargs) -> Optional[Products]:
async def update_market_product(product_id: str, **kwargs) -> Optional[Products]:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
f"UPDATE shop.products SET {q} WHERE id = ?",
f"UPDATE market.products SET {q} WHERE id = ?",
(*kwargs.values(), product_id),
)
row = await db.fetchone("SELECT * FROM shop.products WHERE id = ?", (product_id,))
row = await db.fetchone("SELECT * FROM market.products WHERE id = ?", (product_id,))
return Products(**row) if row else None
async def get_shop_product(product_id: str) -> Optional[Products]:
row = await db.fetchone("SELECT * FROM shop.products WHERE id = ?", (product_id,))
async def get_market_product(product_id: str) -> Optional[Products]:
row = await db.fetchone("SELECT * FROM market.products WHERE id = ?", (product_id,))
return Products(**row) if row else None
async def get_shop_products(stall_ids: Union[str, List[str]]) -> List[Products]:
async def get_market_products(stall_ids: Union[str, List[str]]) -> List[Products]:
if isinstance(stall_ids, str):
stall_ids = [stall_ids]
# with open_ext_db("shop") as db:
# with open_ext_db("market") as db:
q = ",".join(["?"] * len(stall_ids))
rows = await db.fetchall(
f"""
SELECT * FROM shop.products WHERE stall IN ({q})
SELECT * FROM market.products WHERE stall IN ({q})
""",
(*stall_ids,),
)
return [Products(**row) for row in rows]
async def delete_shop_product(product_id: str) -> None:
await db.execute("DELETE FROM shop.products WHERE id = ?", (product_id,))
async def delete_market_product(product_id: str) -> None:
await db.execute("DELETE FROM market.products WHERE id = ?", (product_id,))
###zones
async def create_shop_zone(user, data: createZones) -> Zones:
async def create_market_zone(user, data: createZones) -> Zones:
zone_id = urlsafe_short_hash()
await db.execute(
f"""
INSERT INTO shop.zones (
INSERT INTO market.zones (
id,
"user",
cost,
@@ -108,43 +108,43 @@ async def create_shop_zone(user, data: createZones) -> Zones:
(zone_id, user, data.cost, data.countries.lower()),
)
zone = await get_shop_zone(zone_id)
zone = await get_market_zone(zone_id)
assert zone, "Newly created zone couldn't be retrieved"
return zone
async def update_shop_zone(zone_id: str, **kwargs) -> Optional[Zones]:
async def update_market_zone(zone_id: str, **kwargs) -> Optional[Zones]:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
f"UPDATE shop.zones SET {q} WHERE id = ?",
f"UPDATE market.zones SET {q} WHERE id = ?",
(*kwargs.values(), zone_id),
)
row = await db.fetchone("SELECT * FROM shop.zones WHERE id = ?", (zone_id,))
row = await db.fetchone("SELECT * FROM market.zones WHERE id = ?", (zone_id,))
return Zones(**row) if row else None
async def get_shop_zone(zone_id: str) -> Optional[Zones]:
row = await db.fetchone("SELECT * FROM shop.zones WHERE id = ?", (zone_id,))
async def get_market_zone(zone_id: str) -> Optional[Zones]:
row = await db.fetchone("SELECT * FROM market.zones WHERE id = ?", (zone_id,))
return Zones(**row) if row else None
async def get_shop_zones(user: str) -> List[Zones]:
rows = await db.fetchall('SELECT * FROM shop.zones WHERE "user" = ?', (user,))
async def get_market_zones(user: str) -> List[Zones]:
rows = await db.fetchall('SELECT * FROM market.zones WHERE "user" = ?', (user,))
return [Zones(**row) for row in rows]
async def delete_shop_zone(zone_id: str) -> None:
await db.execute("DELETE FROM shop.zones WHERE id = ?", (zone_id,))
async def delete_market_zone(zone_id: str) -> None:
await db.execute("DELETE FROM market.zones WHERE id = ?", (zone_id,))
###Stalls
async def create_shop_stall(data: createStalls) -> Stalls:
async def create_market_stall(data: createStalls) -> Stalls:
stall_id = urlsafe_short_hash()
await db.execute(
f"""
INSERT INTO shop.stalls (
INSERT INTO market.stalls (
id,
wallet,
name,
@@ -166,56 +166,56 @@ async def create_shop_stall(data: createStalls) -> Stalls:
),
)
stall = await get_shop_stall(stall_id)
stall = await get_market_stall(stall_id)
assert stall, "Newly created stall couldn't be retrieved"
return stall
async def update_shop_stall(stall_id: str, **kwargs) -> Optional[Stalls]:
async def update_market_stall(stall_id: str, **kwargs) -> Optional[Stalls]:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
await db.execute(
f"UPDATE shop.stalls SET {q} WHERE id = ?",
f"UPDATE market.stalls SET {q} WHERE id = ?",
(*kwargs.values(), stall_id),
)
row = await db.fetchone("SELECT * FROM shop.stalls WHERE id = ?", (stall_id,))
row = await db.fetchone("SELECT * FROM market.stalls WHERE id = ?", (stall_id,))
return Stalls(**row) if row else None
async def get_shop_stall(stall_id: str) -> Optional[Stalls]:
row = await db.fetchone("SELECT * FROM shop.stalls WHERE id = ?", (stall_id,))
async def get_market_stall(stall_id: str) -> Optional[Stalls]:
row = await db.fetchone("SELECT * FROM market.stalls WHERE id = ?", (stall_id,))
return Stalls(**row) if row else None
async def get_shop_stalls(wallet_ids: Union[str, List[str]]) -> List[Stalls]:
async def get_market_stalls(wallet_ids: Union[str, List[str]]) -> List[Stalls]:
q = ",".join(["?"] * len(wallet_ids))
rows = await db.fetchall(
f"SELECT * FROM shop.stalls WHERE wallet IN ({q})", (*wallet_ids,)
f"SELECT * FROM market.stalls WHERE wallet IN ({q})", (*wallet_ids,)
)
return [Stalls(**row) for row in rows]
async def get_shop_stalls_by_ids(stall_ids: Union[str, List[str]]) -> List[Stalls]:
async def get_market_stalls_by_ids(stall_ids: Union[str, List[str]]) -> List[Stalls]:
q = ",".join(["?"] * len(stall_ids))
rows = await db.fetchall(
f"SELECT * FROM shop.stalls WHERE id IN ({q})", (*stall_ids,)
f"SELECT * FROM market.stalls WHERE id IN ({q})", (*stall_ids,)
)
return [Stalls(**row) for row in rows]
async def delete_shop_stall(stall_id: str) -> None:
await db.execute("DELETE FROM shop.stalls WHERE id = ?", (stall_id,))
async def delete_market_stall(stall_id: str) -> None:
await db.execute("DELETE FROM market.stalls WHERE id = ?", (stall_id,))
###Orders
async def create_shop_order(data: createOrder, invoiceid: str):
async def create_market_order(data: createOrder, invoiceid: str):
returning = "" if db.type == SQLITE else "RETURNING ID"
method = db.execute if db.type == SQLITE else db.fetchone
result = await (method)(
f"""
INSERT INTO shop.orders (wallet, shippingzone, address, email, total, invoiceid, paid, shipped)
INSERT INTO market.orders (wallet, shippingzone, address, email, total, invoiceid, paid, shipped)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
{returning}
""",
@@ -236,12 +236,12 @@ async def create_shop_order(data: createOrder, invoiceid: str):
return result[0]
async def create_shop_order_details(order_id: str, data: List[createOrderDetails]):
async def create_market_order_details(order_id: str, data: List[createOrderDetails]):
for item in data:
item_id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO shop.order_details (id, order_id, product_id, quantity)
INSERT INTO market.order_details (id, order_id, product_id, quantity)
VALUES (?, ?, ?, ?)
""",
(
@@ -251,34 +251,34 @@ async def create_shop_order_details(order_id: str, data: List[createOrderDetails
item.quantity,
),
)
order_details = await get_shop_order_details(order_id)
order_details = await get_market_order_details(order_id)
return order_details
async def get_shop_order_details(order_id: str) -> List[OrderDetail]:
async def get_market_order_details(order_id: str) -> List[OrderDetail]:
rows = await db.fetchall(
f"SELECT * FROM shop.order_details WHERE order_id = ?", (order_id,)
f"SELECT * FROM market.order_details WHERE order_id = ?", (order_id,)
)
return [OrderDetail(**row) for row in rows]
async def get_shop_order(order_id: str) -> Optional[Orders]:
row = await db.fetchone("SELECT * FROM shop.orders WHERE id = ?", (order_id,))
async def get_market_order(order_id: str) -> Optional[Orders]:
row = await db.fetchone("SELECT * FROM market.orders WHERE id = ?", (order_id,))
return Orders(**row) if row else None
async def get_shop_order_invoiceid(invoice_id: str) -> Optional[Orders]:
async def get_market_order_invoiceid(invoice_id: str) -> Optional[Orders]:
row = await db.fetchone(
"SELECT * FROM shop.orders WHERE invoiceid = ?", (invoice_id,)
"SELECT * FROM market.orders WHERE invoiceid = ?", (invoice_id,)
)
return Orders(**row) if row else None
async def set_shop_order_paid(payment_hash: str):
async def set_market_order_paid(payment_hash: str):
await db.execute(
"""
UPDATE shop.orders
UPDATE market.orders
SET paid = true
WHERE invoiceid = ?
""",
@@ -286,10 +286,10 @@ async def set_shop_order_paid(payment_hash: str):
)
async def set_shop_order_pubkey(payment_hash: str, pubkey: str):
async def set_market_order_pubkey(payment_hash: str, pubkey: str):
await db.execute(
"""
UPDATE shop.orders
UPDATE market.orders
SET pubkey = ?
WHERE invoiceid = ?
""",
@@ -300,7 +300,7 @@ async def set_shop_order_pubkey(payment_hash: str, pubkey: str):
)
async def update_shop_product_stock(products):
async def update_market_product_stock(products):
q = "\n".join(
[f"""WHEN id='{p.product_id}' THEN quantity - {p.quantity}""" for p in products]
@@ -309,7 +309,7 @@ async def update_shop_product_stock(products):
await db.execute(
f"""
UPDATE shop.products
UPDATE market.products
SET quantity=(CASE
{q}
END)
@@ -319,51 +319,51 @@ async def update_shop_product_stock(products):
)
async def get_shop_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]:
async def get_market_orders(wallet_ids: Union[str, List[str]]) -> List[Orders]:
if isinstance(wallet_ids, str):
wallet_ids = [wallet_ids]
q = ",".join(["?"] * len(wallet_ids))
rows = await db.fetchall(
f"SELECT * FROM shop.orders WHERE wallet IN ({q})", (*wallet_ids,)
f"SELECT * FROM market.orders WHERE wallet IN ({q})", (*wallet_ids,)
)
#
return [Orders(**row) for row in rows]
async def delete_shop_order(order_id: str) -> None:
await db.execute("DELETE FROM shop.orders WHERE id = ?", (order_id,))
async def delete_market_order(order_id: str) -> None:
await db.execute("DELETE FROM market.orders WHERE id = ?", (order_id,))
### Market/Marketplace
async def get_shop_markets(user: str) -> List[Market]:
rows = await db.fetchall("SELECT * FROM shop.markets WHERE usr = ?", (user,))
async def get_market_markets(user: str) -> List[Market]:
rows = await db.fetchall("SELECT * FROM market.markets WHERE usr = ?", (user,))
return [Market(**row) for row in rows]
async def get_shop_market(market_id: str) -> Optional[Market]:
row = await db.fetchone("SELECT * FROM shop.markets WHERE id = ?", (market_id,))
async def get_market_market(market_id: str) -> Optional[Market]:
row = await db.fetchone("SELECT * FROM market.markets WHERE id = ?", (market_id,))
return Market(**row) if row else None
async def get_shop_market_stalls(market_id: str):
async def get_market_market_stalls(market_id: str):
rows = await db.fetchall(
"SELECT * FROM shop.market_stalls WHERE marketid = ?", (market_id,)
"SELECT * FROM market.market_stalls WHERE marketid = ?", (market_id,)
)
ids = [row["stallid"] for row in rows]
return await get_shop_stalls_by_ids(ids)
return await get_market_stalls_by_ids(ids)
async def create_shop_market(data: CreateMarket):
async def create_market_market(data: CreateMarket):
market_id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO shop.markets (id, usr, name)
INSERT INTO market.markets (id, usr, name)
VALUES (?, ?, ?)
""",
(
@@ -372,18 +372,18 @@ async def create_shop_market(data: CreateMarket):
data.name,
),
)
market = await get_shop_market(market_id)
market = await get_market_market(market_id)
assert market, "Newly created market couldn't be retrieved"
return market
async def create_shop_market_stalls(market_id: str, data: List[str]):
async def create_market_market_stalls(market_id: str, data: List[str]):
for stallid in data:
id = urlsafe_short_hash()
await db.execute(
"""
INSERT INTO shop.market_stalls (id, marketid, stallid)
INSERT INTO market.market_stalls (id, marketid, stallid)
VALUES (?, ?, ?)
""",
(
@@ -392,21 +392,21 @@ async def create_shop_market_stalls(market_id: str, data: List[str]):
stallid,
),
)
market_stalls = await get_shop_market_stalls(market_id)
market_stalls = await get_market_market_stalls(market_id)
return market_stalls
async def update_shop_market(market_id: str, name: str):
async def update_market_market(market_id: str, name: str):
await db.execute(
"UPDATE shop.markets SET name = ? WHERE id = ?",
"UPDATE market.markets SET name = ? WHERE id = ?",
(name, market_id),
)
await db.execute(
"DELETE FROM shop.market_stalls WHERE marketid = ?",
"DELETE FROM market.market_stalls WHERE marketid = ?",
(market_id,),
)
market = await get_shop_market(market_id)
market = await get_market_market(market_id)
return market
@@ -416,7 +416,7 @@ async def update_shop_market(market_id: str, name: str):
async def create_chat_message(data: CreateChatMessage):
await db.execute(
"""
INSERT INTO shop.messages (msg, pubkey, id_conversation)
INSERT INTO market.messages (msg, pubkey, id_conversation)
VALUES (?, ?, ?)
""",
(
@@ -427,44 +427,44 @@ async def create_chat_message(data: CreateChatMessage):
)
async def get_shop_latest_chat_messages(room_name: str):
async def get_market_latest_chat_messages(room_name: str):
rows = await db.fetchall(
"SELECT * FROM shop.messages WHERE id_conversation = ? ORDER BY timestamp DESC LIMIT 20",
"SELECT * FROM market.messages WHERE id_conversation = ? ORDER BY timestamp DESC LIMIT 20",
(room_name,),
)
return [ChatMessage(**row) for row in rows]
async def get_shop_chat_messages(room_name: str):
async def get_market_chat_messages(room_name: str):
rows = await db.fetchall(
"SELECT * FROM shop.messages WHERE id_conversation = ? ORDER BY timestamp DESC",
"SELECT * FROM market.messages WHERE id_conversation = ? ORDER BY timestamp DESC",
(room_name,),
)
return [ChatMessage(**row) for row in rows]
async def get_shop_chat_by_merchant(ids: List[str]) -> List[ChatMessage]:
async def get_market_chat_by_merchant(ids: List[str]) -> List[ChatMessage]:
q = ",".join(["?"] * len(ids))
rows = await db.fetchall(
f"SELECT * FROM shop.messages WHERE id_conversation IN ({q})",
f"SELECT * FROM market.messages WHERE id_conversation IN ({q})",
(*ids,),
)
return [ChatMessage(**row) for row in rows]
async def get_shop_settings(user) -> Optional[ShopSettings]:
row = await db.fetchone("""SELECT * FROM shop.settings WHERE "user" = ?""", (user,))
async def get_market_settings(user) -> Optional[MarketSettings]:
row = await db.fetchone("""SELECT * FROM market.settings WHERE "user" = ?""", (user,))
return ShopSettings(**row) if row else None
return MarketSettings(**row) if row else None
async def create_shop_settings(user: str, data):
async def create_market_settings(user: str, data):
await db.execute(
"""
INSERT INTO shop.settings ("user", currency, fiat_base_multiplier)
INSERT INTO market.settings ("user", currency, fiat_base_multiplier)
VALUES (?, ?, ?)
""",
(
@@ -475,10 +475,10 @@ async def create_shop_settings(user: str, data):
)
async def set_shop_settings(user: str, data):
async def set_market_settings(user: str, data):
await db.execute(
"""
UPDATE shop.settings
UPDATE market.settings
SET currency = ?, fiat_base_multiplier = ?
WHERE "user" = ?;
""",

View File

@@ -1,10 +1,10 @@
async def m001_initial(db):
"""
Initial Shop settings table.
Initial Market settings table.
"""
await db.execute(
"""
CREATE TABLE shop.settings (
CREATE TABLE market.settings (
"user" TEXT PRIMARY KEY,
currency TEXT DEFAULT 'sat',
fiat_base_multiplier INTEGER DEFAULT 1
@@ -17,7 +17,7 @@ async def m001_initial(db):
"""
await db.execute(
"""
CREATE TABLE shop.stalls (
CREATE TABLE market.stalls (
id TEXT PRIMARY KEY,
wallet TEXT NOT NULL,
name TEXT NOT NULL,
@@ -35,7 +35,7 @@ async def m001_initial(db):
"""
await db.execute(
f"""
CREATE TABLE shop.products (
CREATE TABLE market.products (
id TEXT PRIMARY KEY,
stall TEXT NOT NULL REFERENCES {db.references_schema}stalls (id) ON DELETE CASCADE,
product TEXT NOT NULL,
@@ -54,7 +54,7 @@ async def m001_initial(db):
"""
await db.execute(
"""
CREATE TABLE shop.zones (
CREATE TABLE market.zones (
id TEXT PRIMARY KEY,
"user" TEXT NOT NULL,
cost TEXT NOT NULL,
@@ -68,7 +68,7 @@ async def m001_initial(db):
"""
await db.execute(
f"""
CREATE TABLE shop.orders (
CREATE TABLE market.orders (
id {db.serial_primary_key},
wallet TEXT NOT NULL,
username TEXT,
@@ -92,7 +92,7 @@ async def m001_initial(db):
"""
await db.execute(
f"""
CREATE TABLE shop.order_details (
CREATE TABLE market.order_details (
id TEXT PRIMARY KEY,
order_id INTEGER NOT NULL REFERENCES {db.references_schema}orders (id) ON DELETE CASCADE,
product_id TEXT NOT NULL REFERENCES {db.references_schema}products (id) ON DELETE CASCADE,
@@ -106,7 +106,7 @@ async def m001_initial(db):
"""
await db.execute(
"""
CREATE TABLE shop.markets (
CREATE TABLE market.markets (
id TEXT PRIMARY KEY,
usr TEXT NOT NULL,
name TEXT
@@ -119,7 +119,7 @@ async def m001_initial(db):
"""
await db.execute(
f"""
CREATE TABLE shop.market_stalls (
CREATE TABLE market.market_stalls (
id TEXT PRIMARY KEY,
marketid TEXT NOT NULL REFERENCES {db.references_schema}markets (id) ON DELETE CASCADE,
stallid TEXT NOT NULL REFERENCES {db.references_schema}stalls (id) ON DELETE CASCADE
@@ -132,7 +132,7 @@ async def m001_initial(db):
"""
await db.execute(
f"""
CREATE TABLE shop.messages (
CREATE TABLE market.messages (
id {db.serial_primary_key},
msg TEXT NOT NULL,
pubkey TEXT NOT NULL,
@@ -149,8 +149,8 @@ async def m001_initial(db):
Create indexes for message fetching
"""
await db.execute(
"CREATE INDEX idx_messages_timestamp ON shop.messages (timestamp DESC)"
"CREATE INDEX idx_messages_timestamp ON market.messages (timestamp DESC)"
)
await db.execute(
"CREATE INDEX idx_messages_conversations ON shop.messages (id_conversation)"
"CREATE INDEX idx_messages_conversations ON market.messages (id_conversation)"
)

View File

@@ -4,7 +4,7 @@ from fastapi.param_functions import Query
from pydantic import BaseModel
class ShopSettings(BaseModel):
class MarketSettings(BaseModel):
user: str
currency: str
fiat_base_multiplier: int

View File

@@ -10,8 +10,8 @@ from collections import defaultdict
from fastapi import WebSocket
from loguru import logger
from lnbits.extensions.shop.crud import create_chat_message
from lnbits.extensions.shop.models import CreateChatMessage
from lnbits.extensions.market.crud import create_chat_message
from lnbits.extensions.market.models import CreateChatMessage
class Notifier:

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -6,10 +6,10 @@ from lnbits.core.models import Payment
from lnbits.tasks import register_invoice_listener
from .crud import (
get_shop_order_details,
get_shop_order_invoiceid,
set_shop_order_paid,
update_shop_product_stock,
get_market_order_details,
get_market_order_invoiceid,
set_market_order_paid,
update_market_product_stock,
)
@@ -26,17 +26,17 @@ async def on_invoice_paid(payment: Payment) -> None:
if not payment.extra:
return
if payment.extra.get("tag") != "shop":
if payment.extra.get("tag") != "market":
return
order = await get_shop_order_invoiceid(payment.payment_hash)
order = await get_market_order_invoiceid(payment.payment_hash)
if not order:
logger.error("this should never happen", payment)
return
# set order as paid
await set_shop_order_paid(payment.payment_hash)
await set_market_order_paid(payment.payment_hash)
# deduct items sold from stock
details = await get_shop_order_details(order.id)
await update_shop_product_stock(details)
details = await get_market_order_details(order.id)
await update_market_product_stock(details)

View File

@@ -7,7 +7,7 @@
<q-card>
<q-card-section>
<h5 class="text-subtitle1 q-my-none">
LNbits Shop (Nostr support coming soon)
LNbits Market (Nostr support coming soon)
</h5>
<ol>
@@ -17,9 +17,9 @@
<li>Take orders</li>
<li>Includes chat support!</li>
</ol>
The first LNbits shop idea 'Diagon Alley' helped create Nostr, and soon
this shop extension will have the option to work on Nostr 'Diagon Alley'
mode, by the merchant, shop, and buyer all having keys, and data being
The first LNbits market idea 'Diagon Alley' helped create Nostr, and soon
this market extension will have the option to work on Nostr 'Diagon Alley'
mode, by the merchant, market, and buyer all having keys, and data being
routed through Nostr relays.
<br />
<small>
@@ -48,7 +48,7 @@
<q-card-section>
<code
><span class="text-light-blue">GET</span>
/shop/api/v1/stall/products/&lt;relay_id&gt;</code
/market/api/v1/stall/products/&lt;relay_id&gt;</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
<h5 class="text-caption q-mt-sm q-mb-none">
@@ -73,7 +73,7 @@
<q-card-section>
<code
><span class="text-light-green">POST</span>
/shop/api/v1/stall/order/&lt;relay_id&gt;</code
/market/api/v1/stall/order/&lt;relay_id&gt;</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Body (application/json)</h5>
<code
@@ -109,7 +109,7 @@
<q-card-section>
<code
><span class="text-light-blue">GET</span>
/shop/api/v1/stall/checkshipped/&lt;checking_id&gt;</code
/market/api/v1/stall/checkshipped/&lt;checking_id&gt;</code
>
<h5 class="text-caption q-mt-sm q-mb-none">Headers</h5>
<h5 class="text-caption q-mt-sm q-mb-none">

View File

@@ -184,7 +184,7 @@
</q-form>
</q-card>
</q-dialog>
<!-- MARKETPLACE/SHOP DIALOG -->
<!-- MARKETPLACE/market DIALOG -->
<q-dialog v-model="marketDialog.show" position="top">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendMarketplaceFormData" class="q-gutter-md">
@@ -314,8 +314,8 @@
v-if="diagonAlley"
filled
dense
v-model.trim="stallDialog.data.nostrShops"
label="Nostr shop public keys (seperate by comma)"
v-model.trim="stallDialog.data.nostrMarkets"
label="Nostr market public keys (seperate by comma)"
></q-input>
<div class="row q-mt-lg">
@@ -350,7 +350,7 @@
<!-- ONBOARDING DIALOG -->
<q-dialog v-model="onboarding.show">
<q-card class="q-pa-lg">
<h6 class="q-my-md text-primary">How to use Shop</h6>
<h6 class="q-my-md text-primary">How to use Market</h6>
<q-stepper v-model="step" color="primary" vertical animated>
<q-step
:name="1"

View File

@@ -67,7 +67,7 @@
dense
size="xs"
@click="shipOrder(props.row.id)"
icon="add_shopping_cart"
icon="add_marketping_cart"
color="green"
>
<q-tooltip> Product shipped? </q-tooltip>
@@ -194,7 +194,7 @@
unelevated
dense
size="xs"
icon="add_shopping_cart"
icon="add_marketping_cart"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="props.row.wallet"
@@ -276,10 +276,10 @@
icon="storefront"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="'/shop/stalls/' + props.row.id"
:href="'/market/stalls/' + props.row.id"
target="_blank"
></q-btn>
<q-tooltip> Stall simple UI shopping cart </q-tooltip>
<q-tooltip> Stall simple UI marketping cart </q-tooltip>
</q-td>
<q-td v-for="col in props.cols" :key="col.name" :props="props">
{{ col.value }}
@@ -348,7 +348,7 @@
icon="storefront"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="'/shop/market/' + props.row.id"
:href="'/market/market/' + props.row.id"
target="_blank"
></q-btn>
<q-tooltip> Link to pass to stall relay </q-tooltip>

View File

@@ -1,7 +1,7 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %}
<div class="row q-col-gutter-md">
{% include "shop/_dialogs.html" %}
{% include "market/_dialogs.html" %}
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
<q-card>
<q-card-section class="q-gutter-sm row">
@@ -60,14 +60,14 @@
@click="marketDialog.show = true"
>Create Market
<q-tooltip>
Makes a simple frontend shop for your stalls (not NOSTR)</q-tooltip
Makes a simple frontend market for your stalls (not NOSTR)</q-tooltip
></q-btn
>
</q-card-section>
<q-separator inset></q-separator>
<q-card-section>
<div class="text-h6">Shop</div>
<div class="text-subtitle2">Make a shop of multiple stalls.</div>
<div class="text-h6">Market</div>
<div class="text-subtitle2">Make a market of multiple stalls.</div>
</q-card-section>
<q-card-section>
@@ -87,16 +87,16 @@
class="float-right"
unelevated
color="primary"
@click="shopDataDownload"
@click="marketDataDownload"
>Export all Data
<q-tooltip>
Export all data (shops, products, orders, etc...)</q-tooltip
Export all data (markets, products, orders, etc...)</q-tooltip
></q-btn
>
</q-card-section>
</q-card>
{% include "shop/_tables.html" %}
{% include "market/_tables.html" %}
<!-- KEYS -->
<q-card v-if="keys">
<q-card-section>
@@ -149,16 +149,16 @@
<q-card>
<q-card-section>
<h6 class="text-subtitle1 q-my-none">
LNbits Shop Extension, powered by Nostr
LNbits Market Extension (Nostr support coming soon)
</h6>
</q-card-section>
<q-card-section class="q-pa-none">
<q-separator></q-separator>
<q-list> {% include "shop/_api_docs.html" %} </q-list>
<q-list> {% include "market/_api_docs.html" %} </q-list>
</q-card-section>
</q-card>
<!-- CHAT BOX -->
{% include "shop/_chat_box.html" %}
{% include "market/_chat_box.html" %}
</div>
</div>
@@ -215,7 +215,7 @@
obj._data = _.clone(obj)
obj.stalls = []
LNbits.api
.request('GET', `/shop/api/v1/markets/${obj.id}/stalls`, null)
.request('GET', `/market/api/v1/markets/${obj.id}/stalls`, null)
.then(response => {
if (response.data) {
obj.stalls = response.data.map(s => s.id) //.toString()
@@ -548,7 +548,7 @@
LNbits.api
.request(
'PUT',
'/shop/api/v1/settings/' + this.g.user.id,
'/market/api/v1/settings/' + this.g.user.id,
this.g.user.wallets[0].adminkey,
data
)
@@ -563,7 +563,7 @@
LNbits.utils.notifyApiError(error)
})
},
shopDataDownload() {
marketDataDownload() {
const removeClone = obj => {
delete obj._data
return obj
@@ -593,10 +593,10 @@
this.keys = {privkey, pubkey}
this.stallDialog.data.publickey = this.keys.pubkey
this.stallDialog.data.privatekey = this.keys.privkey
this.$q.localStorage.set(`lnbits.shop.${this.g.user.id}`, this.keys)
this.$q.localStorage.set(`lnbits.market.${this.g.user.id}`, this.keys)
},
restoreKeys() {
let keys = this.$q.localStorage.getItem(`lnbits.shop.${this.g.user.id}`)
let keys = this.$q.localStorage.getItem(`lnbits.market.${this.g.user.id}`)
if (keys) {
this.keys = keys
this.stallDialog.data.publickey = this.keys.pubkey
@@ -645,7 +645,7 @@
LNbits.api
.request(
'GET',
'/shop/api/v1/stalls?all_wallets=true',
'/market/api/v1/stalls?all_wallets=true',
self.g.user.wallets[0].adminkey
)
.then(function (response) {
@@ -704,7 +704,7 @@
LNbits.api
.request(
'PUT',
'/shop/api/v1/stalls/' + data.id,
'/market/api/v1/stalls/' + data.id,
_.findWhere(self.g.user.wallets, {
id: self.stallDialog.data.wallet
}).inkey,
@@ -726,7 +726,7 @@
LNbits.api
.request(
'POST',
'/shop/api/v1/stalls',
'/market/api/v1/stalls',
_.findWhere(self.g.user.wallets, {
id: self.stallDialog.data.wallet
}).inkey,
@@ -753,7 +753,7 @@
LNbits.api
.request(
'DELETE',
'/shop/api/v1/stalls/' + stallId,
'/market/api/v1/stalls/' + stallId,
_.findWhere(self.g.user.wallets, {id: stall.wallet}).adminkey
)
.then(function (response) {
@@ -778,7 +778,7 @@
LNbits.api
.request(
'GET',
'/shop/api/v1/products?all_stalls=true',
'/market/api/v1/products?all_stalls=true',
self.g.user.wallets[0].inkey
)
.then(function (response) {
@@ -851,7 +851,7 @@
LNbits.api
.request(
'PUT',
'/shop/api/v1/products/' + data.id,
'/market/api/v1/products/' + data.id,
_.findWhere(self.g.user.wallets, {
id: wallet
}).inkey,
@@ -877,7 +877,7 @@
LNbits.api
.request(
'POST',
'/shop/api/v1/products',
'/market/api/v1/products',
_.findWhere(self.g.user.wallets, {id: walletId}).inkey,
data
)
@@ -899,7 +899,7 @@
LNbits.api
.request(
'DELETE',
'/shop/api/v1/products/' + productId,
'/market/api/v1/products/' + productId,
_.findWhere(this.g.user.wallets, {id: walletId}).adminkey
)
.then(() => {
@@ -922,7 +922,7 @@
var self = this
LNbits.api
.request('GET', '/shop/api/v1/zones', this.g.user.wallets[0].inkey)
.request('GET', '/market/api/v1/zones', this.g.user.wallets[0].inkey)
.then(function (response) {
if (response.data) {
self.zones = response.data.map(mapZone)
@@ -960,7 +960,7 @@
LNbits.api
.request(
'POST',
'/shop/api/v1/zones/' + data.id,
'/market/api/v1/zones/' + data.id,
self.g.user.wallets[0].adminkey,
data
)
@@ -982,7 +982,7 @@
LNbits.api
.request(
'POST',
'/shop/api/v1/zones',
'/market/api/v1/zones',
self.g.user.wallets[0].inkey,
data
)
@@ -1006,7 +1006,7 @@
LNbits.api
.request(
'DELETE',
'/shop/api/v1/zones/' + zoneId,
'/market/api/v1/zones/' + zoneId,
self.g.user.wallets[0].adminkey
)
.then(function (response) {
@@ -1027,7 +1027,7 @@
////////////////////////////////////////
getMarkets() {
LNbits.api
.request('GET', '/shop/api/v1/markets', this.g.user.wallets[0].inkey)
.request('GET', '/market/api/v1/markets', this.g.user.wallets[0].inkey)
.then(response => {
if (response.data) {
this.markets = response.data.map(mapMarkets)
@@ -1059,7 +1059,7 @@
LNbits.api
.request(
'PUT',
'/shop/api/v1/markets/' + data.id,
'/market/api/v1/markets/' + data.id,
this.g.user.wallets[0].inkey,
data
)
@@ -1080,7 +1080,7 @@
LNbits.api
.request(
'POST',
'/shop/api/v1/markets',
'/market/api/v1/markets',
this.g.user.wallets[0].inkey,
data
)
@@ -1094,8 +1094,8 @@
LNbits.utils.notifyApiError(error)
})
},
deleteMarket(shopId) {
let market = _.findWhere(this.markets, {id: shopId})
deleteMarket(marketId) {
let market = _.findWhere(this.markets, {id: marketId})
LNbits.utils
.confirmDialog('Are you sure you want to delete this Marketplace?')
@@ -1103,12 +1103,12 @@
LNbits.api
.request(
'DELETE',
'/shop/api/v1/markets/' + shopId,
'/market/api/v1/markets/' + marketId,
this.g.user.wallets[0].inkey
)
.then(response => {
this.markets = _.reject(this.markets, obj => {
return obj.id == shopId
return obj.id == marketId
})
})
.catch(function (error) {
@@ -1116,8 +1116,8 @@
})
})
},
exportShopsCSV: function () {
LNbits.utils.exportCSV(this.shopsTable.columns, this.markets)
exportMarketsCSV: function () {
LNbits.utils.exportCSV(this.marketsTable.columns, this.markets)
},
////////////////////////////////////////
////////////////ORDERS//////////////////
@@ -1128,7 +1128,7 @@
await LNbits.api
.request(
'GET',
'/shop/api/v1/orders?all_wallets=true',
'/market/api/v1/orders?all_wallets=true',
this.g.user.wallets[0].inkey
)
.then(response => {
@@ -1150,7 +1150,7 @@
LNbits.api
.request(
'DELETE',
'/shop/api/v1/orders/' + orderId,
'/market/api/v1/orders/' + orderId,
_.findWhere(self.g.user.wallets, {id: order.wallet}).adminkey
)
.then(function (response) {
@@ -1168,7 +1168,7 @@
LNbits.api
.request(
'GET',
`/shop/api/v1/orders/shipped/${order_id}?shipped=${!shipped}`,
`/market/api/v1/orders/shipped/${order_id}?shipped=${!shipped}`,
this.g.user.wallets[0].inkey
)
.then(response => {
@@ -1189,7 +1189,7 @@
await LNbits.api
.request(
'GET',
`/shop/api/v1/chat/messages/merchant?orders=${this.orders
`/market/api/v1/chat/messages/merchant?orders=${this.orders
.map(o => o.invoiceid)
.toString()}`,
this.g.user.wallets[0].adminkey
@@ -1205,7 +1205,7 @@
})
},
updateLastSeenMsg(id) {
let data = this.$q.localStorage.getItem(`lnbits.shop.chat`)
let data = this.$q.localStorage.getItem(`lnbits.market.chat`)
let chat = {
...data,
[`${id}`]: {
@@ -1214,11 +1214,11 @@
]
}
}
this.$q.localStorage.set(`lnbits.shop.chat`, chat)
this.$q.localStorage.set(`lnbits.market.chat`, chat)
this.checkUnreadMessages()
},
checkUnreadMessages() {
let lastMsgs = this.$q.localStorage.getItem(`lnbits.shop.chat`) || {}
let lastMsgs = this.$q.localStorage.getItem(`lnbits.market.chat`) || {}
for (let key in this.messages) {
let idx = this.orders.findIndex(f => f.invoiceid == key)
@@ -1287,7 +1287,7 @@
if (this.ws.readyState === WebSocket.CLOSED) {
console.log('WebSocket CLOSED: Reopening')
this.ws = new WebSocket(
ws_scheme + location.host + '/shop/ws/' + this.customerKey
ws_scheme + location.host + '/market/ws/' + this.customerKey
)
}
},
@@ -1318,7 +1318,7 @@
} else {
ws_scheme = 'ws://'
}
ws = new WebSocket(ws_scheme + location.host + '/shop/ws/' + room_name)
ws = new WebSocket(ws_scheme + location.host + '/market/ws/' + room_name)
ws.onmessage = async event => {
let event_data = JSON.parse(event.data)
@@ -1335,7 +1335,7 @@
},
async getCurrencies() {
await LNbits.api
.request('GET', '/shop/api/v1/currencies')
.request('GET', '/market/api/v1/currencies')
.then(response => {
this.currencies.units = ['sat', ...response.data]
})
@@ -1359,7 +1359,7 @@
await this.getOrders()
this.getMarkets()
await this.getAllMessages()
let keys = this.$q.localStorage.getItem(`lnbits.shop.${this.g.user.id}`)
let keys = this.$q.localStorage.getItem(`lnbits.market.${this.g.user.id}`)
if (keys) {
this.keys = keys
}

View File

@@ -33,7 +33,7 @@
<q-card class="card--product">
{% raw %}
<q-img
:src="item.image ? item.image : '/shop/static/images/placeholder.png'"
:src="item.image ? item.image : '/market/static/images/placeholder.png'"
alt="Product Image"
loading="lazy"
spinner-color="white"
@@ -98,7 +98,7 @@
dense
color="primary"
type="a"
:href="'/shop/stalls/' + item.stall"
:href="'/market/stalls/' + item.stall"
target="_blank"
>
Visit Stall

View File

@@ -292,7 +292,7 @@
lnbitsBookmark: {
show: true,
finish: () => {
this.$q.localStorage.set('lnbits.shopbookmark', false)
this.$q.localStorage.set('lnbits.marketbookmark', false)
this.lnbitsBookmark.show = false
}
},
@@ -368,8 +368,8 @@
},
restoreKeys() {
this.user.keys = this.keysDialog.data
let data = this.$q.localStorage.getItem(`lnbits.shop.data`)
this.$q.localStorage.set(`lnbits.shop.data`, {
let data = this.$q.localStorage.getItem(`lnbits.market.data`)
this.$q.localStorage.set(`lnbits.market.data`, {
...data,
keys: this.user.keys
})
@@ -380,7 +380,7 @@
LNbits.utils
.confirmDialog('Are you sure you want to delete your stored data?')
.onOk(() => {
this.$q.localStorage.remove('lnbits.shop.data')
this.$q.localStorage.remove('lnbits.market.data')
this.user = null
})
},
@@ -401,7 +401,7 @@
await LNbits.api
.request(
'GET',
`/shop/api/v1/chat/messages/${room_name}${
`/market/api/v1/chat/messages/${room_name}${
all ? '?all_messages=true' : ''
}`
)
@@ -430,7 +430,7 @@
if (this.ws.readyState === WebSocket.CLOSED) {
console.log('WebSocket CLOSED: Reopening')
this.ws = new WebSocket(
ws_scheme + location.host + '/shop/ws/' + this.selectedOrder
ws_scheme + location.host + '/market/ws/' + this.selectedOrder
)
}
},
@@ -443,7 +443,7 @@
} else {
ws_scheme = 'ws://'
}
ws = new WebSocket(ws_scheme + location.host + '/shop/ws/' + room_name)
ws = new WebSocket(ws_scheme + location.host + '/market/ws/' + room_name)
ws.onmessage = event => {
let event_data = JSON.parse(event.data)
@@ -455,7 +455,7 @@
}
},
async created() {
let showBookmark = this.$q.localStorage.getItem('lnbits.shopbookmark')
let showBookmark = this.$q.localStorage.getItem('lnbits.marketbookmark')
this.lnbitsBookmark.show = showBookmark === true || showBookmark == null
let order_details = JSON.parse('{{ order | tojson }}')
@@ -488,7 +488,7 @@
this.products = this.products.map(mapProductsItems)
}
let data = this.$q.localStorage.getItem(`lnbits.shop.data`) || false
let data = this.$q.localStorage.getItem(`lnbits.market.data`) || false
if (data) {
this.user = data
@@ -501,7 +501,7 @@
try {
await LNbits.api.request(
'GET',
`/shop/api/v1/order/pubkey/${order_id}/${this.user.keys.publickey}`
`/market/api/v1/order/pubkey/${order_id}/${this.user.keys.publickey}`
)
} catch (error) {
LNbits.utils.notifyApiError(error)
@@ -516,7 +516,7 @@
await this.getMessages(order_id)
this.$q.localStorage.set(`lnbits.shop.data`, this.user)
this.$q.localStorage.set(`lnbits.market.data`, this.user)
this.startChat(order_id)
}
})

View File

@@ -94,7 +94,7 @@
<q-card class="card--product">
{% raw %}
<q-img
:src="item.image ? item.image : '/shop/static/images/placeholder.png'"
:src="item.image ? item.image : '/market/static/images/placeholder.png'"
alt="Product Image"
loading="lazy"
spinner-color="white"
@@ -431,7 +431,7 @@
console.log(this.cart, this.cartMenu)
},
getPubkey() {
let data = this.$q.localStorage.getItem(`lnbits.shop.data`)
let data = this.$q.localStorage.getItem(`lnbits.market.data`)
if (data && data.keys.publickey) {
this.checkoutDialog.data.pubkey = data.keys.publickey
} else {
@@ -456,7 +456,7 @@
})
}
LNbits.api
.request('POST', '/shop/api/v1/orders', null, data)
.request('POST', '/market/api/v1/orders', null, data)
.then(res => {
this.checkoutDialog = {show: false, data: {}}
@@ -477,7 +477,7 @@
LNbits.api
.request(
'GET',
`/shop/api/v1/orders/payments/${this.qrCodeDialog.data.payment_hash}`
`/market/api/v1/orders/payments/${this.qrCodeDialog.data.payment_hash}`
)
.then(res => {
if (res.data.paid) {
@@ -491,7 +491,7 @@
{
label: 'See Order',
handler: () => {
window.location.href = `/shop/order/?merch=${this.stall.id}&invoice_id=${this.qrCodeDialog.data.payment_hash}`
window.location.href = `/market/order/?merch=${this.stall.id}&invoice_id=${this.qrCodeDialog.data.payment_hash}`
}
}
]
@@ -500,7 +500,7 @@
this.resetCart()
this.closeQrCodeDialog()
setTimeout(() => {
window.location.href = `/shop/order/?merch=${this.stall.id}&invoice_id=${this.qrCodeDialog.data.payment_hash}`
window.location.href = `/market/order/?merch=${this.stall.id}&invoice_id=${this.qrCodeDialog.data.payment_hash}`
}, 5000)
}
})

View File

@@ -17,48 +17,48 @@ from starlette.responses import HTMLResponse
from lnbits.core.models import User
from lnbits.decorators import check_user_exists # type: ignore
from lnbits.extensions.shop import shop_ext, shop_renderer
from lnbits.extensions.shop.models import CreateChatMessage, SetSettings
from lnbits.extensions.shop.notifier import Notifier
from lnbits.extensions.market import market_ext, market_renderer
from lnbits.extensions.market.models import CreateChatMessage, SetSettings
from lnbits.extensions.market.notifier import Notifier
from .crud import (
create_chat_message,
create_shop_settings,
get_shop_market,
get_shop_market_stalls,
get_shop_order_details,
get_shop_order_invoiceid,
get_shop_products,
get_shop_settings,
get_shop_stall,
get_shop_zone,
get_shop_zones,
update_shop_product_stock,
create_market_settings,
get_market_market,
get_market_market_stalls,
get_market_order_details,
get_market_order_invoiceid,
get_market_products,
get_market_settings,
get_market_stall,
get_market_zone,
get_market_zones,
update_market_product_stock,
)
templates = Jinja2Templates(directory="templates")
@shop_ext.get("/", response_class=HTMLResponse)
@market_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
settings = await get_shop_settings(user=user.id)
settings = await get_market_settings(user=user.id)
if not settings:
await create_shop_settings(
await create_market_settings(
user=user.id, data=SetSettings(currency="sat", fiat_base_multiplier=1)
)
settings = await get_shop_settings(user.id)
settings = await get_market_settings(user.id)
assert settings
return shop_renderer().TemplateResponse(
"shop/index.html",
return market_renderer().TemplateResponse(
"market/index.html",
{"request": request, "user": user.dict(), "currency": settings.currency},
)
@shop_ext.get("/stalls/{stall_id}", response_class=HTMLResponse)
@market_ext.get("/stalls/{stall_id}", response_class=HTMLResponse)
async def stall(request: Request, stall_id):
stall = await get_shop_stall(stall_id)
products = await get_shop_products(stall_id)
stall = await get_market_stall(stall_id)
products = await get_market_products(stall_id)
if not stall:
raise HTTPException(
@@ -67,7 +67,7 @@ async def stall(request: Request, stall_id):
zones = []
for id in stall.shippingzones.split(","):
zone = await get_shop_zone(id)
zone = await get_market_zone(id)
assert zone
z = zone.dict()
zones.append({"label": z["countries"], "cost": z["cost"], "value": z["id"]})
@@ -76,8 +76,8 @@ async def stall(request: Request, stall_id):
_stall["zones"] = zones
return shop_renderer().TemplateResponse(
"shop/stall.html",
return market_renderer().TemplateResponse(
"market/stall.html",
{
"request": request,
"stall": _stall,
@@ -86,21 +86,21 @@ async def stall(request: Request, stall_id):
)
@shop_ext.get("/market/{market_id}", response_class=HTMLResponse)
@market_ext.get("/market/{market_id}", response_class=HTMLResponse)
async def market(request: Request, market_id):
market = await get_shop_market(market_id)
market = await get_market_market(market_id)
if not market:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Marketplace doesn't exist."
)
stalls = await get_shop_market_stalls(market_id)
stalls = await get_market_market_stalls(market_id)
stalls_ids = [stall.id for stall in stalls]
products = [product.dict() for product in await get_shop_products(stalls_ids)]
products = [product.dict() for product in await get_market_products(stalls_ids)]
return shop_renderer().TemplateResponse(
"shop/market.html",
return market_renderer().TemplateResponse(
"market/market.html",
{
"request": request,
"market": market,
@@ -110,23 +110,23 @@ async def market(request: Request, market_id):
)
@shop_ext.get("/order", response_class=HTMLResponse)
@market_ext.get("/order", response_class=HTMLResponse)
async def order_chat(
request: Request,
merch: str = Query(...),
invoice_id: str = Query(...),
keys: str = Query(None),
):
stall = await get_shop_stall(merch)
stall = await get_market_stall(merch)
assert stall
order = await get_shop_order_invoiceid(invoice_id)
order = await get_market_order_invoiceid(invoice_id)
assert order
_order = await get_shop_order_details(order.id)
products = await get_shop_products(stall.id)
_order = await get_market_order_details(order.id)
products = await get_market_products(stall.id)
assert products
return shop_renderer().TemplateResponse(
"shop/order.html",
return market_renderer().TemplateResponse(
"market/order.html",
{
"request": request,
"stall": {
@@ -151,7 +151,7 @@ async def order_chat(
notifier = Notifier()
@shop_ext.websocket("/ws/{room_name}")
@market_ext.websocket("/ws/{room_name}")
async def websocket_endpoint(
websocket: WebSocket, room_name: str, background_tasks: BackgroundTasks
):

View File

@@ -19,44 +19,44 @@ from lnbits.decorators import (
from lnbits.helpers import urlsafe_short_hash
from lnbits.utils.exchange_rates import currencies, get_fiat_rate_satoshis
from . import db, shop_ext
from . import db, market_ext
from .crud import (
create_shop_market,
create_shop_market_stalls,
create_shop_order,
create_shop_order_details,
create_shop_product,
create_shop_settings,
create_shop_stall,
create_shop_zone,
delete_shop_order,
delete_shop_product,
delete_shop_stall,
delete_shop_zone,
get_shop_chat_by_merchant,
get_shop_chat_messages,
get_shop_latest_chat_messages,
get_shop_market,
get_shop_market_stalls,
get_shop_markets,
get_shop_order,
get_shop_order_details,
get_shop_order_invoiceid,
get_shop_orders,
get_shop_product,
get_shop_products,
get_shop_settings,
get_shop_stall,
get_shop_stalls,
get_shop_stalls_by_ids,
get_shop_zone,
get_shop_zones,
set_shop_order_pubkey,
set_shop_settings,
update_shop_market,
update_shop_product,
update_shop_stall,
update_shop_zone,
create_market_market,
create_market_market_stalls,
create_market_order,
create_market_order_details,
create_market_product,
create_market_settings,
create_market_stall,
create_market_zone,
delete_market_order,
delete_market_product,
delete_market_stall,
delete_market_zone,
get_market_chat_by_merchant,
get_market_chat_messages,
get_market_latest_chat_messages,
get_market_market,
get_market_market_stalls,
get_market_markets,
get_market_order,
get_market_order_details,
get_market_order_invoiceid,
get_market_orders,
get_market_product,
get_market_products,
get_market_settings,
get_market_stall,
get_market_stalls,
get_market_stalls_by_ids,
get_market_zone,
get_market_zones,
set_market_order_pubkey,
set_market_settings,
update_market_market,
update_market_product,
update_market_stall,
update_market_zone,
)
from .models import (
CreateMarket,
@@ -76,8 +76,8 @@ from .models import (
### Products
@shop_ext.get("/api/v1/products")
async def api_shop_products(
@market_ext.get("/api/v1/products")
async def api_market_products(
wallet: WalletTypeInfo = Depends(require_invoice_key),
all_stalls: bool = Query(False),
):
@@ -87,104 +87,104 @@ async def api_shop_products(
user = await get_user(wallet.wallet.user)
wallet_ids = user.wallet_ids if user else []
stalls = [stall.id for stall in await get_shop_stalls(wallet_ids)]
stalls = [stall.id for stall in await get_market_stalls(wallet_ids)]
if not stalls:
return
return [product.dict() for product in await get_shop_products(stalls)]
return [product.dict() for product in await get_market_products(stalls)]
@shop_ext.post("/api/v1/products")
@shop_ext.put("/api/v1/products/{product_id}")
async def api_shop_product_create(
@market_ext.post("/api/v1/products")
@market_ext.put("/api/v1/products/{product_id}")
async def api_market_product_create(
data: createProduct,
product_id=None,
wallet: WalletTypeInfo = Depends(require_invoice_key),
):
# For fiat currencies,
# we multiply by data.fiat_base_multiplier (usually 100) to save the value in cents.
settings = await get_shop_settings(user=wallet.wallet.user)
settings = await get_market_settings(user=wallet.wallet.user)
assert settings
stall = await get_shop_stall(stall_id=data.stall)
stall = await get_market_stall(stall_id=data.stall)
assert stall
if stall.currency != "sat":
data.price *= settings.fiat_base_multiplier
if product_id:
product = await get_shop_product(product_id)
product = await get_market_product(product_id)
if not product:
return {"message": "Product does not exist."}
# stall = await get_shop_stall(stall_id=product.stall)
# stall = await get_market_stall(stall_id=product.stall)
if stall.wallet != wallet.wallet.id:
return {"message": "Not your product."}
product = await update_shop_product(product_id, **data.dict())
product = await update_market_product(product_id, **data.dict())
else:
product = await create_shop_product(data=data)
product = await create_market_product(data=data)
assert product
return product.dict()
@shop_ext.delete("/api/v1/products/{product_id}")
async def api_shop_products_delete(
@market_ext.delete("/api/v1/products/{product_id}")
async def api_market_products_delete(
product_id, wallet: WalletTypeInfo = Depends(require_admin_key)
):
product = await get_shop_product(product_id)
product = await get_market_product(product_id)
if not product:
return {"message": "Product does not exist."}
stall = await get_shop_stall(product.stall)
stall = await get_market_stall(product.stall)
assert stall
if stall.wallet != wallet.wallet.id:
return {"message": "Not your Shop."}
return {"message": "Not your Market."}
await delete_shop_product(product_id)
await delete_market_product(product_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
# # # Shippingzones
@shop_ext.get("/api/v1/zones")
async def api_shop_zones(wallet: WalletTypeInfo = Depends(get_key_type)):
@market_ext.get("/api/v1/zones")
async def api_market_zones(wallet: WalletTypeInfo = Depends(get_key_type)):
return await get_shop_zones(wallet.wallet.user)
return await get_market_zones(wallet.wallet.user)
@shop_ext.post("/api/v1/zones")
async def api_shop_zone_create(
@market_ext.post("/api/v1/zones")
async def api_market_zone_create(
data: createZones, wallet: WalletTypeInfo = Depends(get_key_type)
):
zone = await create_shop_zone(user=wallet.wallet.user, data=data)
zone = await create_market_zone(user=wallet.wallet.user, data=data)
return zone.dict()
@shop_ext.post("/api/v1/zones/{zone_id}")
async def api_shop_zone_update(
@market_ext.post("/api/v1/zones/{zone_id}")
async def api_market_zone_update(
data: createZones,
zone_id: str,
wallet: WalletTypeInfo = Depends(require_admin_key),
):
zone = await get_shop_zone(zone_id)
zone = await get_market_zone(zone_id)
if not zone:
return {"message": "Zone does not exist."}
if zone.user != wallet.wallet.user:
return {"message": "Not your record."}
zone = await update_shop_zone(zone_id, **data.dict())
zone = await update_market_zone(zone_id, **data.dict())
return zone
@shop_ext.delete("/api/v1/zones/{zone_id}")
async def api_shop_zone_delete(
@market_ext.delete("/api/v1/zones/{zone_id}")
async def api_market_zone_delete(
zone_id, wallet: WalletTypeInfo = Depends(require_admin_key)
):
zone = await get_shop_zone(zone_id)
zone = await get_market_zone(zone_id)
if not zone:
return {"message": "zone does not exist."}
@@ -192,15 +192,15 @@ async def api_shop_zone_delete(
if zone.user != wallet.wallet.user:
return {"message": "Not your zone."}
await delete_shop_zone(zone_id)
await delete_market_zone(zone_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
# # # Stalls
@shop_ext.get("/api/v1/stalls")
async def api_shop_stalls(
@market_ext.get("/api/v1/stalls")
async def api_market_stalls(
wallet: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)
):
wallet_ids = [wallet.wallet.id]
@@ -209,37 +209,37 @@ async def api_shop_stalls(
user = await get_user(wallet.wallet.user)
wallet_ids = user.wallet_ids if user else []
return [stall.dict() for stall in await get_shop_stalls(wallet_ids)]
return [stall.dict() for stall in await get_market_stalls(wallet_ids)]
@shop_ext.post("/api/v1/stalls")
@shop_ext.put("/api/v1/stalls/{stall_id}")
async def api_shop_stall_create(
@market_ext.post("/api/v1/stalls")
@market_ext.put("/api/v1/stalls/{stall_id}")
async def api_market_stall_create(
data: createStalls,
stall_id: str = None,
wallet: WalletTypeInfo = Depends(require_invoice_key),
):
if stall_id:
stall = await get_shop_stall(stall_id)
stall = await get_market_stall(stall_id)
if not stall:
return {"message": "Withdraw stall does not exist."}
if stall.wallet != wallet.wallet.id:
return {"message": "Not your withdraw stall."}
stall = await update_shop_stall(stall_id, **data.dict())
stall = await update_market_stall(stall_id, **data.dict())
else:
stall = await create_shop_stall(data=data)
stall = await create_market_stall(data=data)
assert stall
return stall.dict()
@shop_ext.delete("/api/v1/stalls/{stall_id}")
async def api_shop_stall_delete(
@market_ext.delete("/api/v1/stalls/{stall_id}")
async def api_market_stall_delete(
stall_id: str, wallet: WalletTypeInfo = Depends(require_admin_key)
):
stall = await get_shop_stall(stall_id)
stall = await get_market_stall(stall_id)
if not stall:
return {"message": "Stall does not exist."}
@@ -247,15 +247,15 @@ async def api_shop_stall_delete(
if stall.wallet != wallet.wallet.id:
return {"message": "Not your Stall."}
await delete_shop_stall(stall_id)
await delete_market_stall(stall_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
###Orders
@shop_ext.get("/api/v1/orders")
async def api_shop_orders(
@market_ext.get("/api/v1/orders")
async def api_market_orders(
wallet: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)
):
wallet_ids = [wallet.wallet.id]
@@ -263,48 +263,48 @@ async def api_shop_orders(
user = await get_user(wallet.wallet.user)
wallet_ids = user.wallet_ids if user else []
orders = await get_shop_orders(wallet_ids)
orders = await get_market_orders(wallet_ids)
if not orders:
return
orders_with_details = []
for order in orders:
_order = order.dict()
_order["details"] = await get_shop_order_details(_order["id"])
_order["details"] = await get_market_order_details(_order["id"])
orders_with_details.append(_order)
try:
return orders_with_details # [order for order in orders]
# return [order.dict() for order in await get_shop_orders(wallet_ids)]
# return [order.dict() for order in await get_market_orders(wallet_ids)]
except:
return {"message": "We could not retrieve the orders."}
@shop_ext.get("/api/v1/orders/{order_id}")
async def api_shop_order_by_id(order_id: str):
order = await get_shop_order(order_id)
@market_ext.get("/api/v1/orders/{order_id}")
async def api_market_order_by_id(order_id: str):
order = await get_market_order(order_id)
assert order
_order = order.dict()
_order["details"] = await get_shop_order_details(order_id)
_order["details"] = await get_market_order_details(order_id)
return _order
@shop_ext.post("/api/v1/orders")
async def api_shop_order_create(data: createOrder):
@market_ext.post("/api/v1/orders")
async def api_market_order_create(data: createOrder):
ref = urlsafe_short_hash()
payment_hash, payment_request = await create_invoice(
wallet_id=data.wallet,
amount=data.total,
memo=f"New order on Diagon alley",
memo=f"New order on Market",
extra={
"tag": "shop",
"tag": "market",
"reference": ref,
},
)
order_id = await create_shop_order(invoiceid=payment_hash, data=data)
order_id = await create_market_order(invoiceid=payment_hash, data=data)
logger.debug(f"ORDER ID {order_id}")
logger.debug(f"PRODUCTS {data.products}")
await create_shop_order_details(order_id=order_id, data=data.products)
await create_market_order_details(order_id=order_id, data=data.products)
return {
"payment_hash": payment_hash,
"payment_request": payment_request,
@@ -312,9 +312,9 @@ async def api_shop_order_create(data: createOrder):
}
@shop_ext.get("/api/v1/orders/payments/{payment_hash}")
async def api_shop_check_payment(payment_hash: str):
order = await get_shop_order_invoiceid(payment_hash)
@market_ext.get("/api/v1/orders/payments/{payment_hash}")
async def api_market_check_payment(payment_hash: str):
order = await get_market_order_invoiceid(payment_hash)
if not order:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Order does not exist."
@@ -328,11 +328,11 @@ async def api_shop_check_payment(payment_hash: str):
return status
@shop_ext.delete("/api/v1/orders/{order_id}")
async def api_shop_order_delete(
@market_ext.delete("/api/v1/orders/{order_id}")
async def api_market_order_delete(
order_id: str, wallet: WalletTypeInfo = Depends(require_admin_key)
):
order = await get_shop_order(order_id)
order = await get_market_order(order_id)
if not order:
return {"message": "Order does not exist."}
@@ -340,17 +340,17 @@ async def api_shop_order_delete(
if order.wallet != wallet.wallet.id:
return {"message": "Not your Order."}
await delete_shop_order(order_id)
await delete_market_order(order_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
# @shop_ext.get("/api/v1/orders/paid/{order_id}")
# async def api_shop_order_paid(
# @market_ext.get("/api/v1/orders/paid/{order_id}")
# async def api_market_order_paid(
# order_id, wallet: WalletTypeInfo = Depends(require_admin_key)
# ):
# await db.execute(
# "UPDATE shop.orders SET paid = ? WHERE id = ?",
# "UPDATE market.orders SET paid = ? WHERE id = ?",
# (
# True,
# order_id,
@@ -359,24 +359,24 @@ async def api_shop_order_delete(
# return "", HTTPStatus.OK
@shop_ext.get("/api/v1/order/pubkey/{payment_hash}/{pubkey}")
async def api_shop_order_pubkey(payment_hash: str, pubkey: str):
await set_shop_order_pubkey(payment_hash, pubkey)
@market_ext.get("/api/v1/order/pubkey/{payment_hash}/{pubkey}")
async def api_market_order_pubkey(payment_hash: str, pubkey: str):
await set_market_order_pubkey(payment_hash, pubkey)
return "", HTTPStatus.OK
@shop_ext.get("/api/v1/orders/shipped/{order_id}")
async def api_shop_order_shipped(
@market_ext.get("/api/v1/orders/shipped/{order_id}")
async def api_market_order_shipped(
order_id, shipped: bool = Query(...), wallet: WalletTypeInfo = Depends(get_key_type)
):
await db.execute(
"UPDATE shop.orders SET shipped = ? WHERE id = ?",
"UPDATE market.orders SET shipped = ? WHERE id = ?",
(
shipped,
order_id,
),
)
order = await db.fetchone("SELECT * FROM shop.orders WHERE id = ?", (order_id,))
order = await db.fetchone("SELECT * FROM market.orders WHERE id = ?", (order_id,))
return order
@@ -384,31 +384,31 @@ async def api_shop_order_shipped(
###List products based on stall id
# @shop_ext.get("/api/v1/stall/products/{stall_id}")
# async def api_shop_stall_products(
# @market_ext.get("/api/v1/stall/products/{stall_id}")
# async def api_market_stall_products(
# stall_id, wallet: WalletTypeInfo = Depends(get_key_type)
# ):
# rows = await db.fetchone("SELECT * FROM shop.stalls WHERE id = ?", (stall_id,))
# rows = await db.fetchone("SELECT * FROM market.stalls WHERE id = ?", (stall_id,))
# if not rows:
# return {"message": "Stall does not exist."}
# products = db.fetchone("SELECT * FROM shop.products WHERE wallet = ?", (rows[1],))
# products = db.fetchone("SELECT * FROM market.products WHERE wallet = ?", (rows[1],))
# if not products:
# return {"message": "No products"}
# return [products.dict() for products in await get_shop_products(rows[1])]
# return [products.dict() for products in await get_market_products(rows[1])]
###Check a product has been shipped
# @shop_ext.get("/api/v1/stall/checkshipped/{checking_id}")
# async def api_shop_stall_checkshipped(
# @market_ext.get("/api/v1/stall/checkshipped/{checking_id}")
# async def api_market_stall_checkshipped(
# checking_id, wallet: WalletTypeInfo = Depends(get_key_type)
# ):
# rows = await db.fetchone(
# "SELECT * FROM shop.orders WHERE invoiceid = ?", (checking_id,)
# "SELECT * FROM market.orders WHERE invoiceid = ?", (checking_id,)
# )
# return {"shipped": rows["shipped"]}
@@ -418,42 +418,42 @@ async def api_shop_order_shipped(
##
@shop_ext.get("/api/v1/markets")
async def api_shop_markets(wallet: WalletTypeInfo = Depends(get_key_type)):
# await get_shop_market_stalls(market_id="FzpWnMyHQMcRppiGVua4eY")
@market_ext.get("/api/v1/markets")
async def api_market_markets(wallet: WalletTypeInfo = Depends(get_key_type)):
# await get_market_market_stalls(market_id="FzpWnMyHQMcRppiGVua4eY")
try:
return [market.dict() for market in await get_shop_markets(wallet.wallet.user)]
return [market.dict() for market in await get_market_markets(wallet.wallet.user)]
except:
return {"message": "We could not retrieve the markets."}
@shop_ext.get("/api/v1/markets/{market_id}/stalls")
async def api_shop_market_stalls(market_id: str):
stall_ids = await get_shop_market_stalls(market_id)
@market_ext.get("/api/v1/markets/{market_id}/stalls")
async def api_market_market_stalls(market_id: str):
stall_ids = await get_market_market_stalls(market_id)
return stall_ids
@shop_ext.post("/api/v1/markets")
@shop_ext.put("/api/v1/markets/{market_id}")
async def api_shop_market_create(
@market_ext.post("/api/v1/markets")
@market_ext.put("/api/v1/markets/{market_id}")
async def api_market_market_create(
data: CreateMarket,
market_id: str = None,
wallet: WalletTypeInfo = Depends(require_invoice_key),
):
if market_id:
market = await get_shop_market(market_id)
market = await get_market_market(market_id)
if not market:
return {"message": "Market does not exist."}
if market.usr != wallet.wallet.user:
return {"message": "Not your market."}
market = await update_shop_market(market_id, data.name)
market = await update_market_market(market_id, data.name)
else:
market = await create_shop_market(data=data)
market = await create_market_market(data=data)
assert market
await create_shop_market_stalls(market_id=market.id, data=data.stalls)
await create_market_market_stalls(market_id=market.id, data=data.stalls)
return market.dict()
@@ -461,39 +461,39 @@ async def api_shop_market_create(
## MESSAGES/CHAT
@shop_ext.get("/api/v1/chat/messages/merchant")
@market_ext.get("/api/v1/chat/messages/merchant")
async def api_get_merchant_messages(
orders: str = Query(...), wallet: WalletTypeInfo = Depends(require_admin_key)
):
return [msg.dict() for msg in await get_shop_chat_by_merchant(orders.split(","))]
return [msg.dict() for msg in await get_market_chat_by_merchant(orders.split(","))]
@shop_ext.get("/api/v1/chat/messages/{room_name}")
@market_ext.get("/api/v1/chat/messages/{room_name}")
async def api_get_latest_chat_msg(room_name: str, all_messages: bool = Query(False)):
if all_messages:
messages = await get_shop_chat_messages(room_name)
messages = await get_market_chat_messages(room_name)
else:
messages = await get_shop_latest_chat_messages(room_name)
messages = await get_market_latest_chat_messages(room_name)
return messages
@shop_ext.get("/api/v1/currencies")
@market_ext.get("/api/v1/currencies")
async def api_list_currencies_available():
return list(currencies.keys())
@shop_ext.get("/api/v1/settings")
@market_ext.get("/api/v1/settings")
async def api_get_settings(wallet: WalletTypeInfo = Depends(require_admin_key)):
user = wallet.wallet.user
settings = await get_shop_settings(user)
settings = await get_market_settings(user)
return settings
@shop_ext.post("/api/v1/settings")
@shop_ext.put("/api/v1/settings/{usr}")
@market_ext.post("/api/v1/settings")
@market_ext.put("/api/v1/settings/{usr}")
async def api_set_settings(
data: SetSettings,
usr: str = None,
@@ -501,16 +501,16 @@ async def api_set_settings(
):
if usr:
if usr != wallet.wallet.user:
return {"message": "Not your Shop."}
return {"message": "Not your Market."}
settings = await get_shop_settings(user=usr)
settings = await get_market_settings(user=usr)
assert settings
if settings.user != wallet.wallet.user:
return {"message": "Not your Shop."}
return {"message": "Not your Market."}
return await set_shop_settings(usr, data)
return await set_market_settings(usr, data)
user = wallet.wallet.user
return await create_shop_settings(user, data)
return await create_market_settings(user, data)

View File

@@ -1,6 +0,0 @@
{
"name": "Shop",
"short_description": "Make a webshop on LNbits",
"tile": "/shop/static/images/bitcoin-shop.png",
"contributors": ["benarc", "talvasconcelos"]
}