Added online status
This commit is contained in:
parent
49c0f932ab
commit
54c40c6b85
@ -29,3 +29,5 @@ class UserModel(BaseModel):
|
|||||||
regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
|
regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
|
||||||
)
|
)
|
||||||
password = ModelField(name="password", required=True, min_length=1)
|
password = ModelField(name="password", required=True, min_length=1)
|
||||||
|
|
||||||
|
last_ping = ModelField(name="last_ping", required=False, kind=str)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
from snek.system.service import BaseService
|
from snek.system.service import BaseService
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from snek.system.model import now
|
||||||
|
|
||||||
class ChannelService(BaseService):
|
class ChannelService(BaseService):
|
||||||
mapper_name = "channel"
|
mapper_name = "channel"
|
||||||
@ -29,6 +31,25 @@ class ChannelService(BaseService):
|
|||||||
return model
|
return model
|
||||||
raise Exception(f"Failed to create channel: {model.errors}.")
|
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):
|
async def ensure_public_channel(self, created_by_uid):
|
||||||
model = await self.get(is_listed=True, tag="public")
|
model = await self.get(is_listed=True, tag="public")
|
||||||
is_moderator = False
|
is_moderator = False
|
||||||
|
@ -27,6 +27,7 @@ class UserService(BaseService):
|
|||||||
user['color'] = await self.services.util.random_light_hex_color()
|
user['color'] = await self.services.util.random_light_hex_color()
|
||||||
return await super().save(user)
|
return await super().save(user)
|
||||||
|
|
||||||
|
|
||||||
async def register(self, email, username, password):
|
async def register(self, email, username, password):
|
||||||
if await self.exists(username=username):
|
if await self.exists(username=username):
|
||||||
raise Exception("User already exists.")
|
raise Exception("User already exists.")
|
||||||
|
@ -206,11 +206,14 @@ class Socket extends EventHandler {
|
|||||||
ws.onerror = () => {
|
ws.onerror = () => {
|
||||||
this.onClose();
|
this.onClose();
|
||||||
};
|
};
|
||||||
|
this.onConnect()
|
||||||
this.connectPromises.forEach(resolver => resolver(this));
|
this.connectPromises.forEach(resolver => resolver(this));
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
onConnect(){
|
||||||
|
this.emit("connected")
|
||||||
|
}
|
||||||
onData(data) {
|
onData(data) {
|
||||||
if (data.success !== undefined && !data.success) {
|
if (data.success !== undefined && !data.success) {
|
||||||
console.error(data);
|
console.error(data);
|
||||||
@ -282,12 +285,31 @@ class App extends EventHandler {
|
|||||||
audio = null;
|
audio = null;
|
||||||
user = {};
|
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() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.ws = new Socket();
|
this.ws = new Socket();
|
||||||
this.rpc = this.ws.client;
|
this.rpc = this.ws.client;
|
||||||
this.audio = new NotificationAudio(500);
|
this.audio = new NotificationAudio(500);
|
||||||
|
this.is_pinging = false
|
||||||
|
this.ping_interval = setInterval(()=>{
|
||||||
|
this.ping("active")
|
||||||
|
}, 15000)
|
||||||
|
|
||||||
|
|
||||||
const me = this
|
const me = this
|
||||||
|
this.ws.addEventListener("connected", (data)=> {
|
||||||
|
this.ping("online")
|
||||||
|
})
|
||||||
this.ws.addEventListener("channel-message", (data) => {
|
this.ws.addEventListener("channel-message", (data) => {
|
||||||
me.emit("channel-message", data);
|
me.emit("channel-message", data);
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,7 @@ from aiohttp import web
|
|||||||
from snek.system.view import BaseView
|
from snek.system.view import BaseView
|
||||||
import traceback
|
import traceback
|
||||||
import json
|
import json
|
||||||
|
from snek.system.model import now
|
||||||
|
|
||||||
class RPCView(BaseView):
|
class RPCView(BaseView):
|
||||||
|
|
||||||
@ -133,8 +134,24 @@ class RPCView(BaseView):
|
|||||||
|
|
||||||
async def _send_json(self, obj):
|
async def _send_json(self, obj):
|
||||||
await self.ws.send_str(json.dumps(obj, default=str))
|
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}
|
return {"pong": args}
|
||||||
|
|
||||||
async def get(self):
|
async def get(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user