temporary move

This commit is contained in:
2025-01-29 16:36:18 +01:00
parent 561a915e30
commit d7c003c409
91 changed files with 0 additions and 366 deletions
+31
View File
@@ -0,0 +1,31 @@
import functools
from snek.service.channel import ChannelService
from snek.service.channel_member import ChannelMemberService
from snek.service.channel_message import ChannelMessageService
from snek.service.chat import ChatService
from snek.service.notification import NotificationService
from snek.service.socket import SocketService
from snek.service.user import UserService
from snek.service.util import UtilService
from snek.system.object import Object
@functools.cache
def get_services(app):
return Object(
**{
"user": UserService(app=app),
"channel_member": ChannelMemberService(app=app),
"channel": ChannelService(app=app),
"channel_message": ChannelMessageService(app=app),
"chat": ChatService(app=app),
"socket": SocketService(app=app),
"notification": NotificationService(app=app),
"util": UtilService(app=app),
}
)
def get_service(name, app=None):
return get_services(app=app)[name]
+48
View File
@@ -0,0 +1,48 @@
from snek.system.service import BaseService
class ChannelService(BaseService):
mapper_name = "channel"
async def create(
self,
label,
created_by_uid,
description=None,
tag=None,
is_private=False,
is_listed=True,
):
if label[0] != "#" and is_listed:
label = f"#{label}"
count = await self.count(deleted_at=None)
if not tag and not count:
tag = "public"
model = await self.new()
model["label"] = label
model["description"] = description
model["tag"] = tag
model["created_by_uid"] = created_by_uid
model["is_private"] = is_private
model["is_listed"] = is_listed
if await self.save(model):
return model
raise Exception(f"Failed to create channel: {model.errors}.")
async def ensure_public_channel(self, created_by_uid):
model = await self.get(is_listed=True, tag="public")
is_moderator = False
if not model:
is_moderator = True
model = await self.create(
"public", created_by_uid=created_by_uid, is_listed=True, tag="public"
)
await self.app.services.channel_member.create(
model["uid"],
created_by_uid,
is_moderator=is_moderator,
is_read_only=False,
is_muted=False,
is_banned=False,
)
return model
+34
View File
@@ -0,0 +1,34 @@
from snek.system.service import BaseService
class ChannelMemberService(BaseService):
mapper_name = "channel_member"
async def create(
self,
channel_uid,
user_uid,
is_moderator=False,
is_read_only=False,
is_muted=False,
is_banned=False,
):
model = await self.get(channel_uid=channel_uid, user_uid=user_uid)
if model:
if model.is_banned.value:
return False
return model
model = await self.new()
channel = await self.services.channel.get(uid=channel_uid)
model["label"] = channel["label"]
model["channel_uid"] = channel_uid
model["user_uid"] = user_uid
model["is_moderator"] = is_moderator
model["is_read_only"] = is_read_only
model["is_muted"] = is_muted
model["is_banned"] = is_banned
print(model.record, flush=True)
if await self.save(model):
return model
raise Exception(f"Failed to create channel member: {model.errors}.")
+40
View File
@@ -0,0 +1,40 @@
from snek.system.service import BaseService
import jinja2
class ChannelMessageService(BaseService):
mapper_name = "channel_message"
async def create(self, channel_uid, user_uid, message):
model = await self.new()
model["channel_uid"] = channel_uid
model["user_uid"] = user_uid
model["message"] = message
context = {
}
record = model.record
context.update(record)
user = await self.app.services.user.get(uid=user_uid)
context.update(dict(
user_uid=user['uid'],
username=user['username'],
user_nick=user['nick']
))
try:
template = self.app.jinja2_env.get_template("message.html")
model["html"] = template.render(**context)
except Exception as ex:
print(ex,flush=True)
print("RENDER",flush=True)
print("RECORD",context,flush=True)
print("AFTER RENDER",flush=True)
if await self.save(model):
return model
raise Exception(f"Failed to create channel message: {model.errors}.")
+30
View File
@@ -0,0 +1,30 @@
from snek.system.service import BaseService
class ChatService(BaseService):
async def send(self,user_uid, channel_uid, message):
channel_message = await self.services.channel_message.create(
channel_uid,
user_uid,
message
)
channel_message_uid = channel_message["uid"]
user = await self.services.user.get(uid=user_uid)
await self.services.notification.create_channel_message(channel_message_uid)
sent_to_count = await self.services.socket.broadcast(channel_uid, dict(
message=channel_message["message"],
html=channel_message["html"],
user_uid=user_uid,
color=user['color'],
channel_uid=channel_uid,
created_at=channel_message["created_at"],
updated_at=None,
uid=channel_message['uid'],
user_nick=user['nick']
))
return sent_to_count
+37
View File
@@ -0,0 +1,37 @@
from snek.system.service import BaseService
class NotificationService(BaseService):
mapper_name = "notification"
async def create(self, object_uid, object_type, user_uid, message):
model = await self.new()
model["object_uid"] = object_uid
model["object_type"] = object_type
model["user_uid"] = user_uid
model["message"] = message
if await self.save(model):
return model
raise Exception(f"Failed to create notification: {model.errors}.")
async def create_channel_message(self, channel_message_uid):
channel_message = await self.services.channel_message.get(
uid=channel_message_uid
)
user = await self.services.user.get(uid=channel_message["user_uid"])
async for channel_member in self.services.channel_member.find(
channel_uid=channel_message["channel_uid"],
is_banned=False,
is_muted=False,
deleted_at=None,
):
model = await self.new()
model["object_uid"] = channel_message_uid
model["object_type"] = "channel_message"
model["user_uid"] = channel_member["user_uid"]
model["message"] = (
f"New message from {user['nick']} in {channel_member['label']}."
)
if await self.save(model):
return model
raise Exception(f"Failed to create notification: {model.errors}.")
+40
View File
@@ -0,0 +1,40 @@
from snek.system.service import BaseService
class SocketService(BaseService):
def __init__(self, app):
super().__init__(app)
self.sockets = set()
self.subscriptions = {}
async def add(self, ws):
self.sockets.add(ws)
async def subscribe(self, ws, channel_uid):
if not channel_uid in self.subscriptions:
self.subscriptions[channel_uid] = set()
self.subscriptions[channel_uid].add(ws)
async def broadcast(self, channel_uid, message):
print("BROADCAT!",message)
count = 0
subscriptions = set(self.subscriptions.get(channel_uid,[]))
for ws in subscriptions:
try:
await ws.send_json(message)
except Exception as ex:
print(ex)
print("Deleting socket.")
self.subscriptions[channel_uid].remove(ws)
continue
count += 1
return count
async def delete(self, ws):
try:
self.sockets.remove(ws)
except IndexError:
pass
+38
View File
@@ -0,0 +1,38 @@
from snek.system import security
from snek.system.service import BaseService
class UserService(BaseService):
mapper_name = "user"
async def validate_login(self, username, password):
model = await self.get(username=username)
if not model:
return False
if not await security.verify(password, model["password"]):
return False
return True
async def save(self, user):
if not user['color']:
user['color'] = await self.services.util.random_light_hex_color()
return await super().save(user)
async def register(self, email, username, password):
if await self.exists(username=username):
raise Exception("User already exists.")
model = await self.new()
model["nick"] = username
model['color'] = await self.services.util.random_light_hex_color()
model.email.value = email
model.username.value = username
model.password.value = await security.hash(password)
if await self.save(model):
if model:
channel = await self.services.channel.ensure_public_channel(
model["uid"]
)
if not channel:
raise Exception("Failed to create public channel.")
return model
raise Exception(f"Failed to create user: {model.errors}.")
+15
View File
@@ -0,0 +1,15 @@
import random
from snek.system.service import BaseService
class UtilService(BaseService):
async def random_light_hex_color(self):
r = random.randint(128, 255)
g = random.randint(128, 255)
b = random.randint(128, 255)
return "#{:02x}{:02x}{:02x}".format(r, g, b)