temporary move
This commit is contained in:
@@ -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]
|
||||
@@ -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
|
||||
@@ -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}.")
|
||||
@@ -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}.")
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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}.")
|
||||
@@ -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
|
||||
@@ -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}.")
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user