Added online status

This commit is contained in:
retoor 2025-02-10 16:18:08 +01:00
parent 49c0f932ab
commit 54c40c6b85
5 changed files with 65 additions and 2 deletions

View File

@ -29,3 +29,5 @@ class UserModel(BaseModel):
regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
)
password = ModelField(name="password", required=True, min_length=1)
last_ping = ModelField(name="last_ping", required=False, kind=str)

View File

@ -1,5 +1,7 @@
from snek.system.service import BaseService
from datetime import datetime
from snek.system.model import now
class ChannelService(BaseService):
mapper_name = "channel"
@ -29,6 +31,25 @@ class ChannelService(BaseService):
return model
raise Exception(f"Failed to create channel: {model.errors}.")
async def get_users(self, channel_uid):
users = []
async for channel_member in self.services.channel_member.find(
channel_uid=channel_uid,
is_banned=False,
is_muted=False,
deleted_at=None,
):
yield await self.services.user.get(uid=channel_member["user_uid"])
async def get_online_users(self, channel_uid):
users = []
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() < 30:
yield user
async def ensure_public_channel(self, created_by_uid):
model = await self.get(is_listed=True, tag="public")
is_moderator = False

View File

@ -27,6 +27,7 @@ class UserService(BaseService):
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.")

View File

@ -206,11 +206,14 @@ class Socket extends EventHandler {
ws.onerror = () => {
this.onClose();
};
this.onConnect()
this.connectPromises.forEach(resolver => resolver(this));
};
});
}
onConnect(){
this.emit("connected")
}
onData(data) {
if (data.success !== undefined && !data.success) {
console.error(data);
@ -282,12 +285,31 @@ class App extends EventHandler {
audio = null;
user = {};
async ping(...args) {
if(this.is_pinging)return false
this.is_pinging = true
await this.rpc.ping(...args);
this.is_pinging = false
}
async forcePing(...arg) {
await this.rpc.ping(...args);
}
constructor() {
super();
this.ws = new Socket();
this.rpc = this.ws.client;
this.audio = new NotificationAudio(500);
this.is_pinging = false
this.ping_interval = setInterval(()=>{
this.ping("active")
}, 15000)
const me = this
this.ws.addEventListener("connected", (data)=> {
this.ping("online")
})
this.ws.addEventListener("channel-message", (data) => {
me.emit("channel-message", data);
});

View File

@ -11,6 +11,7 @@ from aiohttp import web
from snek.system.view import BaseView
import traceback
import json
from snek.system.model import now
class RPCView(BaseView):
@ -134,7 +135,23 @@ class RPCView(BaseView):
async def _send_json(self, obj):
await self.ws.send_str(json.dumps(obj, default=str))
async def call_ping(self, callId, *args):
async def get_online_users(self, channel_uid):
self._require_login()
return [dict(uid=record['uid'],username=record['username'], nick=record['nick']) async for record in self.services.channel.get_online_users(channel_uid)]
async def get_users(self, channel_uid):
self._require_login()
return [dict(uid=record['uid'],username=record['username'], nick=record['nick']) async for record in self.services.channel.get_users(channel_uid)]
async def ping(self, callId, *args):
if self.user_uid:
user = await self.services.user.get(uid=self.user_uid)
user['last_ping'] = now()
await self.services.user.save(user)
return {"pong": args}
async def get(self):