Files
snek/src/snek/service/channel.py
T
2025-06-14 12:34:26 +02:00

139 lines
4.6 KiB
Python

import pathlib
from datetime import datetime
from snek.system.model import now
from snek.system.service import BaseService
class ChannelService(BaseService):
mapper_name = "channel"
async def get_home_folder(self, channel_uid):
folder = pathlib.Path(f"./drive/{channel_uid}/container/home")
if not folder.exists():
try:
folder.mkdir(parents=True, exist_ok=True)
except:
pass
return folder
async def get_attachment_folder(self, channel_uid, ensure=False):
path = pathlib.Path(f"./drive/{channel_uid}/attachments")
if ensure:
path.mkdir(parents=True, exist_ok=True)
return path
async def get(self, uid=None, **kwargs):
if uid:
kwargs["uid"] = uid
result = await super().get(**kwargs)
if result:
return result
del kwargs["uid"]
kwargs["name"] = uid
result = await super().get(**kwargs)
if result:
return result
kwargs["name"] = "#" + uid
result = await super().get(**kwargs)
if result:
return result
return None
return await super().get(**kwargs)
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):
await self.services.container.create(model["uid"])
return model
raise Exception(f"Failed to create channel: {model.errors}.")
async def get_dm(self, user1, user2):
channel_member = await self.services.channel_member.get_dm(user1, user2)
if channel_member:
return await self.get(uid=channel_member["channel_uid"])
channel = await self.create("DM", user1, tag="dm")
await self.services.channel_member.create_dm(channel["uid"], user1, user2)
return channel
async def get_recent_users(self, channel_uid):
async for user in self.query(
"SELECT user.uid, user.username,user.color,user.last_ping,user.nick FROM channel_member INNER JOIN user ON user.uid = channel_member.user_uid WHERE channel_uid=:channel_uid AND user.last_ping >= datetime('now', '-3 minutes') ORDER BY last_ping DESC LIMIT 30",
{"channel_uid": channel_uid},
):
yield user
async def get_users(self, channel_uid):
async for channel_member in self.services.channel_member.find(
channel_uid=channel_uid,
is_banned=False,
is_muted=False,
deleted_at=None,
):
user = await self.services.user.get(uid=channel_member["user_uid"])
if user:
yield user
async def get_online_users(self, channel_uid):
async for user in self.get_users(channel_uid):
if not user["last_ping"]:
continue
if (
datetime.fromisoformat(now())
- datetime.fromisoformat(user["last_ping"])
).total_seconds() < 180:
yield user
async def get_for_user(self, user_uid):
async for channel_member in self.services.channel_member.find(
user_uid=user_uid,
is_banned=False,
deleted_at=None,
):
channel = await self.get(uid=channel_member["channel_uid"])
yield channel
async def clear(self, channel_uid):
model = await self.get(uid=channel_uid)
model['history_from'] = datetime.now()
await self.save(model)
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