add barkshark-lib dep
This commit is contained in:
parent
848350684f
commit
026f5bd11d
|
@ -1,7 +1,8 @@
|
||||||
import aputils
|
|
||||||
import click
|
import click
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
|
from aputils import Signer
|
||||||
|
from blib import HttpDate
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from . import TRANS
|
from . import TRANS
|
||||||
|
@ -29,7 +30,7 @@ def cli_setup(ctx: click.Context) -> None:
|
||||||
click.confirm(TRANS.fetch("setup", "prompt-database"), abort = True)
|
click.confirm(TRANS.fetch("setup", "prompt-database"), abort = True)
|
||||||
ctx.obj.config.sqlite_path.unlink()
|
ctx.obj.config.sqlite_path.unlink()
|
||||||
|
|
||||||
current = aputils.HttpDate.new_utc()
|
current = HttpDate.new_utc()
|
||||||
|
|
||||||
with ctx.obj.database.session(True) as s:
|
with ctx.obj.database.session(True) as s:
|
||||||
s.create_tables()
|
s.create_tables()
|
||||||
|
@ -47,10 +48,10 @@ def cli_setup(ctx: click.Context) -> None:
|
||||||
})
|
})
|
||||||
|
|
||||||
click.echo(TRANS.fetch("setup", "create-key", username = ctx.obj.config.host))
|
click.echo(TRANS.fetch("setup", "create-key", username = ctx.obj.config.host))
|
||||||
instance_signer = aputils.Signer.new(f"https://{ctx.obj.config.web_host}/actor")
|
instance_signer = Signer.new(f"https://{ctx.obj.config.web_host}/actor")
|
||||||
|
|
||||||
click.echo(TRANS.fetch("setup", "create-key", username = "relay"))
|
click.echo(TRANS.fetch("setup", "create-key", username = "relay"))
|
||||||
relay_signer = aputils.Signer.new(f"https://{ctx.obj.config.web_host}/relay")
|
relay_signer = Signer.new(f"https://{ctx.obj.config.web_host}/relay")
|
||||||
|
|
||||||
s.insert("user", {
|
s.insert("user", {
|
||||||
"id": -99,
|
"id": -99,
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import aputils
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
|
from aputils import MessageDate
|
||||||
|
from blib import HttpDate, Enum
|
||||||
|
|
||||||
from .connection import Connection
|
from .connection import Connection
|
||||||
from .schema import SCHEMA
|
from .schema import SCHEMA
|
||||||
|
|
||||||
|
|
||||||
sqlite3.register_adapter(aputils.Enum, lambda v: v.value)
|
sqlite3.register_adapter(Enum, lambda v: v.value)
|
||||||
sqlite3.register_adapter(aputils.HttpDate, lambda v: v.timestamp())
|
sqlite3.register_adapter(HttpDate, lambda v: v.timestamp())
|
||||||
sqlite3.register_adapter(aputils.MessageDate, lambda v: v.timestamp())
|
sqlite3.register_adapter(MessageDate, lambda v: v.timestamp())
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from aputils import JsonBase
|
from blib import JsonBase, convert_to_boolean
|
||||||
from bsql import Row, boolean
|
from bsql import Row
|
||||||
|
|
||||||
from collections.abc import Callable, Iterator, Sequence
|
from collections.abc import Callable, Iterator, Sequence
|
||||||
from typing import Any, Generic, Self, TypeVar
|
from typing import Any, Generic, Self, TypeVar
|
||||||
|
@ -9,7 +9,7 @@ from .. import TRANS
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
CONVERTERS: dict[type, tuple[Callable[[str], Any], Callable[[Any], str]]] = {
|
CONVERTERS: dict[type, tuple[Callable[[str], Any], Callable[[Any], str]]] = {
|
||||||
bool: (boolean, str),
|
bool: (convert_to_boolean, str),
|
||||||
int: (int, str),
|
int: (int, str),
|
||||||
dict: (JsonBase.parse, lambda value: JsonBase(value).to_json()),
|
dict: (JsonBase.parse, lambda value: JsonBase(value).to_json()),
|
||||||
str: (str, str)
|
str: (str, str)
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import aputils
|
|
||||||
import bsql
|
|
||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
|
from aputils import Message, MessageDate, Nodeinfo, ObjectType, Signer, Webfinger
|
||||||
from argon2 import PasswordHasher
|
from argon2 import PasswordHasher
|
||||||
from basgi import Application as App
|
from basgi import Application as App
|
||||||
|
from blib import HttpDate
|
||||||
|
from bsql import Connection as BsqlConnection, Row
|
||||||
from collections.abc import Iterator
|
from collections.abc import Iterator
|
||||||
from typing import TYPE_CHECKING, Any, TypeVar
|
from typing import TYPE_CHECKING, Any, TypeVar
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ if TYPE_CHECKING:
|
||||||
T = TypeVar("T", bound = ObjectMixin)
|
T = TypeVar("T", bound = ObjectMixin)
|
||||||
|
|
||||||
|
|
||||||
class Connection(bsql.Connection):
|
class Connection(BsqlConnection):
|
||||||
@property
|
@property
|
||||||
def app(self) -> Application:
|
def app(self) -> Application:
|
||||||
return App.get("BarksharkSocial") # type: ignore[return-value]
|
return App.get("BarksharkSocial") # type: ignore[return-value]
|
||||||
|
@ -100,8 +101,6 @@ class Connection(bsql.Connection):
|
||||||
if not domain:
|
if not domain:
|
||||||
domain = self.config.host
|
domain = self.config.host
|
||||||
|
|
||||||
print(username, domain)
|
|
||||||
|
|
||||||
with self.select("user", username = username, domain = domain) as cur:
|
with self.select("user", username = username, domain = domain) as cur:
|
||||||
return User.from_possible_row(cur.one())
|
return User.from_possible_row(cur.one())
|
||||||
|
|
||||||
|
@ -156,7 +155,7 @@ class Connection(bsql.Connection):
|
||||||
description: str | None = None,
|
description: str | None = None,
|
||||||
short_description: str | None = None) -> Instance:
|
short_description: str | None = None) -> Instance:
|
||||||
|
|
||||||
date = aputils.HttpDate.new_utc()
|
date = HttpDate.new_utc()
|
||||||
data = Instance.new(
|
data = Instance.new(
|
||||||
domain = domain,
|
domain = domain,
|
||||||
web_domain = web_domain,
|
web_domain = web_domain,
|
||||||
|
@ -171,9 +170,9 @@ class Connection(bsql.Connection):
|
||||||
|
|
||||||
|
|
||||||
def put_instance_data(self,
|
def put_instance_data(self,
|
||||||
nodeinfo: aputils.Nodeinfo,
|
nodeinfo: Nodeinfo,
|
||||||
webfinger: aputils.Webfinger,
|
webfinger: Webfinger,
|
||||||
actor: aputils.Message) -> Instance:
|
actor: Message) -> Instance:
|
||||||
|
|
||||||
if self.get_instance(actor.domain) is not None:
|
if self.get_instance(actor.domain) is not None:
|
||||||
raise KeyError("Instance already exists")
|
raise KeyError("Instance already exists")
|
||||||
|
@ -193,7 +192,7 @@ class Connection(bsql.Connection):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
description = None
|
description = None
|
||||||
|
|
||||||
current = aputils.HttpDate.new_utc()
|
current = HttpDate.new_utc()
|
||||||
instance = Instance(
|
instance = Instance(
|
||||||
id = 0 if has_instance else 1,
|
id = 0 if has_instance else 1,
|
||||||
domain = webfinger.domain,
|
domain = webfinger.domain,
|
||||||
|
@ -229,8 +228,8 @@ class Connection(bsql.Connection):
|
||||||
raise ValueError(TRANS.fetch("error", "empty-row"))
|
raise ValueError(TRANS.fetch("error", "empty-row"))
|
||||||
|
|
||||||
TRANS.print("setup", "create-key", username = username)
|
TRANS.print("setup", "create-key", username = username)
|
||||||
signer = aputils.Signer.new(f"https://{instance.web_domain}/user/{username}#main-key")
|
signer = Signer.new(f"https://{instance.web_domain}/user/{username}#main-key")
|
||||||
date = aputils.HttpDate.new_utc()
|
date = HttpDate.new_utc()
|
||||||
data = User(
|
data = User(
|
||||||
id = 0 if has_user else 1,
|
id = 0 if has_user else 1,
|
||||||
username = username,
|
username = username,
|
||||||
|
@ -260,7 +259,7 @@ class Connection(bsql.Connection):
|
||||||
return self.insert_row(data)
|
return self.insert_row(data)
|
||||||
|
|
||||||
|
|
||||||
def put_remote_user(self, actor: aputils.Message) -> User:
|
def put_remote_user(self, actor: Message) -> User:
|
||||||
with self.run("get-at-least-1-user") as cur:
|
with self.run("get-at-least-1-user") as cur:
|
||||||
has_user = cur.one() is not None
|
has_user = cur.one() is not None
|
||||||
|
|
||||||
|
@ -274,7 +273,7 @@ class Connection(bsql.Connection):
|
||||||
date = actor.published
|
date = actor.published
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
date = aputils.MessageDate.now()
|
date = MessageDate.now()
|
||||||
|
|
||||||
data = User(
|
data = User(
|
||||||
id = 0 if has_user else 1,
|
id = 0 if has_user else 1,
|
||||||
|
@ -288,7 +287,7 @@ class Connection(bsql.Connection):
|
||||||
password = None,
|
password = None,
|
||||||
permission = PermissionLevel.REMOTE,
|
permission = PermissionLevel.REMOTE,
|
||||||
locked = actor.manually_approves_followers,
|
locked = actor.manually_approves_followers,
|
||||||
is_bot = actor.type != aputils.ObjectType.PERSON,
|
is_bot = actor.type != ObjectType.PERSON,
|
||||||
private_key = None,
|
private_key = None,
|
||||||
public_key = actor.pubkey,
|
public_key = actor.pubkey,
|
||||||
bio = actor.get("summary", ""),
|
bio = actor.get("summary", ""),
|
||||||
|
@ -348,7 +347,7 @@ class Connection(bsql.Connection):
|
||||||
|
|
||||||
|
|
||||||
def put_cookie(self, user: User, user_agent: str | None) -> Cookie:
|
def put_cookie(self, user: User, user_agent: str | None) -> Cookie:
|
||||||
date = aputils.HttpDate.new_utc()
|
date = HttpDate.new_utc()
|
||||||
params = {
|
params = {
|
||||||
"code": secrets.token_hex(16),
|
"code": secrets.token_hex(16),
|
||||||
"userid": user.id,
|
"userid": user.id,
|
||||||
|
@ -369,7 +368,7 @@ class Connection(bsql.Connection):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_count(row: bsql.Row | None) -> int:
|
def get_count(row: Row | None) -> int:
|
||||||
if not row:
|
if not row:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import aputils
|
|
||||||
import bsql
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
|
from aputils import MessageDate, Signer
|
||||||
|
from blib import HttpDate
|
||||||
|
from bsql import Row
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Self
|
from typing import Any, Self
|
||||||
|
@ -29,7 +30,7 @@ class ObjectMixin:
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row(cls: type[Self], row: bsql.Row | dict[str, Any]) -> Self:
|
def from_row(cls: type[Self], row: Row | dict[str, Any]) -> Self:
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
for key in cls.__dataclass_fields__:
|
for key in cls.__dataclass_fields__:
|
||||||
|
@ -40,7 +41,7 @@ class ObjectMixin:
|
||||||
value = row[key]
|
value = row[key]
|
||||||
|
|
||||||
if isinstance(value, datetime):
|
if isinstance(value, datetime):
|
||||||
value = aputils.MessageDate.parse(value)
|
value = MessageDate.parse(value)
|
||||||
|
|
||||||
data.append(value)
|
data.append(value)
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ class ObjectMixin:
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_possible_row(cls: type[Self], row: bsql.Row | dict[str, Any] | None) -> Self | None:
|
def from_possible_row(cls: type[Self], row: Row | dict[str, Any] | None) -> Self | None:
|
||||||
if row is None:
|
if row is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ class Follow(ObjectMixin):
|
||||||
target.get_instance(connection).id,
|
target.get_instance(connection).id,
|
||||||
followid,
|
followid,
|
||||||
accept,
|
accept,
|
||||||
aputils.HttpDate.new_utc()
|
HttpDate.new_utc()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,11 +178,11 @@ class User(ObjectMixin):
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def signer(self) -> aputils.Signer:
|
def signer(self) -> Signer:
|
||||||
if self.private_key:
|
if self.private_key:
|
||||||
return aputils.Signer(self.private_key, self.actor + "#main-key")
|
return Signer(self.private_key, self.actor + "#main-key")
|
||||||
|
|
||||||
return aputils.Signer(self.public_key, self.actor + "#main-key")
|
return Signer(self.public_key, self.actor + "#main-key")
|
||||||
|
|
||||||
|
|
||||||
# auth middleware stuff
|
# auth middleware stuff
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from aputils import IntEnum, StrEnum
|
from blib import IntEnum, StrEnum
|
||||||
|
|
||||||
|
|
||||||
class PermissionLevel(IntEnum):
|
class PermissionLevel(IntEnum):
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#info
|
#info
|
||||||
.avatar
|
.avatar
|
||||||
%div
|
%div
|
||||||
-if user.domain != state.config.host
|
-if user.domain != app.config.host
|
||||||
%p.handle
|
%p.handle
|
||||||
%a(href="{{user.page_url}}" target="_new") << @{{user.handle}}
|
%a(href="{{user.page_url}}" target="_new") << @{{user.handle}}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,9 @@ import httpx
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from aputils import JsonBase, Message, Signature, SignatureFailureError
|
from aputils import Message, Signature, SignatureFailureError
|
||||||
from basgi import Client, HttpError, Request
|
from basgi import Client, HttpError, Request
|
||||||
|
from blib import JsonBase
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from .database.connection import Connection
|
from .database.connection import Connection
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
from importlib.resources import files as PackageFiles
|
from importlib.resources import files as PackageFiles
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
|
|
||||||
def get_resource(path: str) -> Path:
|
def get_resource(path: str) -> Path:
|
||||||
|
@ -10,31 +9,3 @@ def get_resource(path: str) -> Path:
|
||||||
def read_resource_text(path: str) -> str:
|
def read_resource_text(path: str) -> str:
|
||||||
with get_resource(path).open("r", encoding = "utf-8") as fd:
|
with get_resource(path).open("r", encoding = "utf-8") as fd:
|
||||||
return fd.read()
|
return fd.read()
|
||||||
|
|
||||||
|
|
||||||
class DictProperty:
|
|
||||||
"Provide attribute access to a dict key."
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, key: str):
|
|
||||||
self.key = key
|
|
||||||
|
|
||||||
|
|
||||||
def __get__(self, obj: dict[str, Any] | None, objtype: type[Any] | None = None) -> Any:
|
|
||||||
if obj is None:
|
|
||||||
return self
|
|
||||||
|
|
||||||
try:
|
|
||||||
return obj[self.key]
|
|
||||||
|
|
||||||
except KeyError:
|
|
||||||
objname = object.__class__.__name__
|
|
||||||
raise AttributeError(f"'{objname}' has no attribute '{self.key}'") from None
|
|
||||||
|
|
||||||
|
|
||||||
def __set__(self, obj: dict[str, Any], value: Any) -> None:
|
|
||||||
obj[self.key] = value
|
|
||||||
|
|
||||||
|
|
||||||
def __delete__(self, obj: dict[str, Any]) -> None:
|
|
||||||
del obj[self.key]
|
|
||||||
|
|
|
@ -76,6 +76,10 @@ async def handle_undo(request: Request, message: Message, user: User) -> None:
|
||||||
else:
|
else:
|
||||||
obj = Message.parse(message.object)
|
obj = Message.parse(message.object)
|
||||||
|
|
||||||
|
if obj.type not in ObjectType.Actor:
|
||||||
|
print(repr(obj.type))
|
||||||
|
return
|
||||||
|
|
||||||
if obj.object_id != user.actor:
|
if obj.object_id != user.actor:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"Follow object does not match actor: msg=%s, actor=%s",
|
"Follow object does not match actor: msg=%s, actor=%s",
|
||||||
|
@ -104,6 +108,8 @@ async def handle_undo(request: Request, message: Message, user: User) -> None:
|
||||||
|
|
||||||
|
|
||||||
async def process_message(request: Request, message: Message, user: User) -> None:
|
async def process_message(request: Request, message: Message, user: User) -> None:
|
||||||
|
print(f"process_message: {user.handle}, message:", message.to_json(4), flush = True)
|
||||||
|
|
||||||
if request.state.user.actor != message.actor_id:
|
if request.state.user.actor != message.actor_id:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"Message actor and signature keyid do not match: msg=%s, actor=%s",
|
"Message actor and signature keyid do not match: msg=%s, actor=%s",
|
||||||
|
@ -120,7 +126,7 @@ async def process_message(request: Request, message: Message, user: User) -> Non
|
||||||
logging.error(error.response.read())
|
logging.error(error.response.read())
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logging.debug("Unhandled message type: %s", message.type.name)
|
logging.debug("Unhandled message type: %s", message.type)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
|
@ -59,15 +59,19 @@ async def handle_instance_actor_get(request: Request) -> Response:
|
||||||
async def handle_instance_actor_post(request: Request) -> Response:
|
async def handle_instance_actor_post(request: Request) -> Response:
|
||||||
ensure_signed(request)
|
ensure_signed(request)
|
||||||
|
|
||||||
return Response(202, "UvU")
|
with request.app.state.database.session(False) as s:
|
||||||
|
if (user := s.get_user(request.app.state.config.host)) is None:
|
||||||
|
raise HttpError(404, "User not found")
|
||||||
|
|
||||||
|
message = Message.parse(await request.body())
|
||||||
|
asyncio.create_task(process_message(request, message, user))
|
||||||
|
return Response(200, "uvu")
|
||||||
|
|
||||||
|
|
||||||
@router.get("BarksharkSocial", "/relay")
|
@router.get("BarksharkSocial", "/relay")
|
||||||
async def handle_relay_get(request: Request) -> Response:
|
async def handle_relay_get(request: Request) -> Response:
|
||||||
config = request.app.state.config
|
|
||||||
|
|
||||||
with request.app.state.database.session(False) as s:
|
with request.app.state.database.session(False) as s:
|
||||||
if (user := s.get_user("relay", config.host)) is None:
|
if (user := s.get_user("relay")) is None:
|
||||||
raise HttpError(404, "User not found")
|
raise HttpError(404, "User not found")
|
||||||
|
|
||||||
data = Message.new_actor(
|
data = Message.new_actor(
|
||||||
|
@ -87,7 +91,13 @@ async def handle_relay_get(request: Request) -> Response:
|
||||||
async def handle_relay_post(request: Request) -> Response:
|
async def handle_relay_post(request: Request) -> Response:
|
||||||
ensure_signed(request)
|
ensure_signed(request)
|
||||||
|
|
||||||
return Response(202, "UvU")
|
with request.app.state.database.session(False) as s:
|
||||||
|
if (user := s.get_user("relay")) is None:
|
||||||
|
raise HttpError(404, "User not found")
|
||||||
|
|
||||||
|
message = Message.parse(await request.body())
|
||||||
|
asyncio.create_task(process_message(request, message, user))
|
||||||
|
return Response(200, "uvu")
|
||||||
|
|
||||||
|
|
||||||
@router.get("BarksharkSocial", "/user/{username}")
|
@router.get("BarksharkSocial", "/user/{username}")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from aputils import HttpDate
|
|
||||||
from argon2.exceptions import VerifyMismatchError
|
from argon2.exceptions import VerifyMismatchError
|
||||||
from basgi import HttpError, FileResponse, Request, Response, TemplateResponse, router
|
from basgi import HttpError, FileResponse, Request, Response, TemplateResponse, router
|
||||||
|
from blib import HttpDate
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from ..misc import get_resource
|
from ..misc import get_resource
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import aputils
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from aputils import Signer, register_validator
|
||||||
from argon2 import PasswordHasher
|
from argon2 import PasswordHasher
|
||||||
from bsql import Database
|
from bsql import Database
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -126,8 +126,8 @@ class Application(App[Request, RequestState, AppState]):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@aputils.register_validator(Request)
|
@register_validator(Request)
|
||||||
async def handle_validate_request(signer: aputils.Signer, request: Request) -> bool:
|
async def handle_validate_request(signer: Signer, request: Request) -> bool:
|
||||||
return signer.validate_signature(
|
return signer.validate_signature(
|
||||||
request.method,
|
request.method,
|
||||||
request.path,
|
request.path,
|
||||||
|
|
5
dev.py
5
dev.py
|
@ -130,13 +130,8 @@ def cli_update_files() -> None:
|
||||||
|
|
||||||
|
|
||||||
@cli.command("exec", context_settings = {"allow_extra_args": True})
|
@cli.command("exec", context_settings = {"allow_extra_args": True})
|
||||||
@option("--watch", "-w", is_flag = True)
|
|
||||||
@pass_context
|
@pass_context
|
||||||
def cli_run(ctx: Context, watch: bool = False) -> None:
|
def cli_run(ctx: Context, watch: bool = False) -> None:
|
||||||
if watch:
|
|
||||||
handle_run_watcher("-m", "barkshark_social", *ctx.args)
|
|
||||||
return
|
|
||||||
|
|
||||||
run_python("-m", "barkshark_social", *ctx.args)
|
run_python("-m", "barkshark_social", *ctx.args)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,12 @@ dependencies = [
|
||||||
"argon2-cffi == 23.1.0",
|
"argon2-cffi == 23.1.0",
|
||||||
"barkshark-sql == 0.1.3",
|
"barkshark-sql == 0.1.3",
|
||||||
"click == 8.1.7",
|
"click == 8.1.7",
|
||||||
"itsdangerous == 2.1.2",
|
|
||||||
"pymemcache == 4.0.0",
|
"pymemcache == 4.0.0",
|
||||||
"pyyaml == 6.0.1",
|
"pyyaml == 6.0.1",
|
||||||
"uvicorn[standard] == 0.29.0"
|
"uvicorn[standard] == 0.29.0",
|
||||||
|
|
||||||
|
"barkshark-asgi @ https://git.barkshark.xyz/barkshark/basgi/archive/main.tar.gz",
|
||||||
|
"barkshark-lib @ https://git.barkshark.xyz/barkshark/blib/archive/main.tar.gz"
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|
Loading…
Reference in a new issue