update naming of functions, add option to get count of unread messages of user
This commit is contained in:
@@ -1,410 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
import json
|
|
||||||
import threading
|
|
||||||
import requests
|
|
||||||
import websockets
|
|
||||||
from datetime import datetime
|
|
||||||
from prompt_toolkit import PromptSession
|
|
||||||
from prompt_toolkit.key_binding import KeyBindings
|
|
||||||
from prompt_toolkit.keys import Keys
|
|
||||||
|
|
||||||
BASE_URL = "http://localhost:8080"
|
|
||||||
WS_URI = "ws://localhost:8080/ws"
|
|
||||||
RETRY_DELAY = 2
|
|
||||||
|
|
||||||
token: str | None = None
|
|
||||||
user_id: int | None = None
|
|
||||||
|
|
||||||
bindings = KeyBindings()
|
|
||||||
|
|
||||||
@bindings.add(Keys.Enter)
|
|
||||||
def submit(event):
|
|
||||||
event.current_buffer.validate_and_handle()
|
|
||||||
|
|
||||||
@bindings.add(Keys.Escape, Keys.Enter)
|
|
||||||
def newline(event):
|
|
||||||
event.current_buffer.insert_text("\n")
|
|
||||||
|
|
||||||
send_queue: asyncio.Queue = None
|
|
||||||
loop: asyncio.AbstractEventLoop = None
|
|
||||||
shutdown_event: asyncio.Event = None
|
|
||||||
|
|
||||||
# ── helpers ──────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def post(path, **data):
|
|
||||||
return requests.post(f"{BASE_URL}{path}", data=data)
|
|
||||||
|
|
||||||
def post_auth(path, **data):
|
|
||||||
return requests.post(f"{BASE_URL}{path}", data={"token": token, **data})
|
|
||||||
|
|
||||||
def post_auth_header(path, files=None, **data):
|
|
||||||
return requests.post(f"{BASE_URL}{path}", headers={"token": token}, data=data, files=files)
|
|
||||||
|
|
||||||
def fmt_msg(m: dict) -> str:
|
|
||||||
sender = m.get("sender", "?")
|
|
||||||
content = m.get("content", "")
|
|
||||||
ts = m.get("createdAt", "")
|
|
||||||
try:
|
|
||||||
dt = datetime.fromisoformat(ts.replace("Z", "+00:00"))
|
|
||||||
ts = dt.strftime("%H:%M:%S")
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return f"[{ts}] <{sender}> {content}"
|
|
||||||
|
|
||||||
# ── commands ─────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def cmd_new_user(args):
|
|
||||||
if len(args) < 2:
|
|
||||||
print("usage: /new/user <username> <password>")
|
|
||||||
return
|
|
||||||
r = post("/new/user", username=args[0], password=args[1])
|
|
||||||
print("registered" if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_new_token(args):
|
|
||||||
global token, user_id
|
|
||||||
if len(args) < 2:
|
|
||||||
print("usage: /new/token <username> <password>")
|
|
||||||
return
|
|
||||||
r = post("/new/token", username=args[0], password=args[1])
|
|
||||||
if r.ok:
|
|
||||||
data = r.json()
|
|
||||||
token = data["token"]
|
|
||||||
user_id = data["userId"]
|
|
||||||
print(f"logged in user_id={user_id}")
|
|
||||||
asyncio.run_coroutine_threadsafe(
|
|
||||||
send_queue.put(json.dumps({"token": token})), loop
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
print(f"login failed: {r.text}")
|
|
||||||
|
|
||||||
def cmd_msg_user(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if len(args) < 2:
|
|
||||||
print("usage: /msg/user <connectionid> <message…>")
|
|
||||||
return
|
|
||||||
conn_id = args[0]
|
|
||||||
content = " ".join(args[1:])
|
|
||||||
r = post_auth("/msg/user", connectionid=conn_id, msgContent=content)
|
|
||||||
print("sent" if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_get_connection_messages(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /get/connection/messages <connectionid> [count] [before]")
|
|
||||||
return
|
|
||||||
data = {"connectionid": args[0]}
|
|
||||||
if len(args) > 1:
|
|
||||||
data["messages"] = args[1]
|
|
||||||
if len(args) > 2:
|
|
||||||
data["before"] = args[2]
|
|
||||||
r = post_auth("/get/connection/messages", **data)
|
|
||||||
if r.ok:
|
|
||||||
msgs = r.json() or []
|
|
||||||
if not msgs:
|
|
||||||
print("no messages")
|
|
||||||
for m in msgs:
|
|
||||||
print(fmt_msg(m))
|
|
||||||
else:
|
|
||||||
print(f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_get_connections(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
r = post_auth("/get/connections")
|
|
||||||
if r.ok:
|
|
||||||
for c in (r.json() or []):
|
|
||||||
print(f" {c['id']} requestor={c['requestorId']} recipient={c['recipientId']} state={c['state']}")
|
|
||||||
else:
|
|
||||||
print(f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_new_connection(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /new/connection <userid>")
|
|
||||||
return
|
|
||||||
r = post_auth("/new/connection", recipient=args[0])
|
|
||||||
print("connection requested" if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_mod_connection_elevate(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /mod/connection/elevate <connectionid>")
|
|
||||||
return
|
|
||||||
r = post_auth("/mod/connection/elevate", connectionid=args[0])
|
|
||||||
print(f"ok: {r.text}" if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_del_connection(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /del/connection <connectionid>")
|
|
||||||
return
|
|
||||||
r = post_auth("/del/connection", connectionid=args[0])
|
|
||||||
print("deleted" if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_del_user(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
r = post_auth("/del/user")
|
|
||||||
print("user deleted" if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_get_user(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /get/user <userid>")
|
|
||||||
return
|
|
||||||
r = post_auth("/get/user", targetid=args[0])
|
|
||||||
if r.ok:
|
|
||||||
print(json.dumps(r.json(), indent=2))
|
|
||||||
else:
|
|
||||||
print(f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_mod_user_profile(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
data = {}
|
|
||||||
for arg in args:
|
|
||||||
if "=" in arg:
|
|
||||||
k, v = arg.split("=", 1)
|
|
||||||
data[k] = v
|
|
||||||
if not data:
|
|
||||||
print("usage: /mod/user/profile [pronouns=...] [description=...] [color=r,g,b,a]")
|
|
||||||
return
|
|
||||||
r = post_auth("/mod/user/profile", **data)
|
|
||||||
print("updated" if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_get_file(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if len(args) < 2:
|
|
||||||
print("usage: /get/file <connectionid> <key>")
|
|
||||||
return
|
|
||||||
r = post_auth_header("/get/file", connectionid=args[0], key=args[1])
|
|
||||||
if r.ok:
|
|
||||||
print(json.dumps(r.json(), indent=2))
|
|
||||||
else:
|
|
||||||
print(f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_new_file(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if len(args) < 2:
|
|
||||||
print("usage: /new/file <connectionid> <filepath>")
|
|
||||||
return
|
|
||||||
conn_id, filepath = args[0], args[1]
|
|
||||||
try:
|
|
||||||
with open(filepath, "rb") as f:
|
|
||||||
r = post_auth_header("/new/file", files={"file": f}, connectionid=conn_id)
|
|
||||||
print(f"uploaded: {r.text}" if r.ok else f"error: {r.text}")
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(f"file not found: {filepath}")
|
|
||||||
|
|
||||||
def cmd_mod_user_avatar(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /mod/user/avatar <filepath>")
|
|
||||||
return
|
|
||||||
filepath = args[0]
|
|
||||||
try:
|
|
||||||
with open(filepath, "rb") as f:
|
|
||||||
r = post_auth_header("/mod/user/avatar", files={"file": f})
|
|
||||||
print("avatar updated" if r.ok else f"error: {r.text}")
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(f"file not found: {filepath}")
|
|
||||||
|
|
||||||
def cmd_mod_user_profilebg(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /mod/user/profilebg <filepath>")
|
|
||||||
return
|
|
||||||
filepath = args[0]
|
|
||||||
try:
|
|
||||||
with open(filepath, "rb") as f:
|
|
||||||
r = post_auth_header("/mod/user/profilebg", files={"file": f})
|
|
||||||
print("profile background updated" if r.ok else f"error: {r.text}")
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(f"file not found: {filepath}")
|
|
||||||
|
|
||||||
def cmd_get_user_avatar(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /get/user/avatar <userid>")
|
|
||||||
return
|
|
||||||
r = post_auth_header("/get/user/avatar", userid=args[0])
|
|
||||||
print(r.text if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
def cmd_get_user_profilebg(args):
|
|
||||||
if not token:
|
|
||||||
print("not logged in")
|
|
||||||
return
|
|
||||||
if not args:
|
|
||||||
print("usage: /get/user/profilebg <userid>")
|
|
||||||
return
|
|
||||||
r = post_auth_header("/get/user/profilebg", userid=args[0])
|
|
||||||
print(r.text if r.ok else f"error: {r.text}")
|
|
||||||
|
|
||||||
COMMANDS = {
|
|
||||||
"/new/user": cmd_new_user,
|
|
||||||
"/new/token": cmd_new_token,
|
|
||||||
"/new/connection": cmd_new_connection,
|
|
||||||
"/new/file": cmd_new_file,
|
|
||||||
"/mod/user/profile": cmd_mod_user_profile,
|
|
||||||
"/mod/user/avatar": cmd_mod_user_avatar,
|
|
||||||
"/mod/user/profilebg": cmd_mod_user_profilebg,
|
|
||||||
"/mod/connection/elevate": cmd_mod_connection_elevate,
|
|
||||||
"/get/user": cmd_get_user,
|
|
||||||
"/get/connections": cmd_get_connections,
|
|
||||||
"/get/connection/messages": cmd_get_connection_messages,
|
|
||||||
"/get/file": cmd_get_file,
|
|
||||||
"/get/user/avatar": cmd_get_user_avatar,
|
|
||||||
"/get/user/profilebg": cmd_get_user_profilebg,
|
|
||||||
"/del/user": cmd_del_user,
|
|
||||||
"/del/connection": cmd_del_connection,
|
|
||||||
"/msg/user": cmd_msg_user,
|
|
||||||
}
|
|
||||||
|
|
||||||
HELP = """
|
|
||||||
/new/user <user> <pass> – create account
|
|
||||||
/new/token <user> <pass> – authenticate
|
|
||||||
/new/connection <userid> – send connection request
|
|
||||||
/new/file <connectionid> <filepath> – upload attachment
|
|
||||||
/mod/user/profile [pronouns=...] [description=...] [color=r,g,b,a] – update profile
|
|
||||||
/mod/user/avatar <filepath> – set avatar image
|
|
||||||
/mod/user/profilebg <filepath> – set profile background
|
|
||||||
/mod/connection/elevate <connectionid> – elevate connection
|
|
||||||
/get/user <userid> – get user info
|
|
||||||
/get/connections – list your connections
|
|
||||||
/get/connection/messages <connectionid> [count] [before] – fetch message history
|
|
||||||
/get/file <connectionid> <key> – download attachment URL
|
|
||||||
/get/user/avatar <userid> – get avatar download URL
|
|
||||||
/get/user/profilebg <userid> – get profile background URL
|
|
||||||
/del/user – delete your account
|
|
||||||
/del/connection <connectionid> – delete a connection
|
|
||||||
/msg/user <connectionid> <message…> – send a DM
|
|
||||||
"""
|
|
||||||
|
|
||||||
# ── websocket ─────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
async def receiver(ws):
|
|
||||||
async for raw in ws:
|
|
||||||
try:
|
|
||||||
data = json.loads(raw)
|
|
||||||
if "content" in data and "sender" in data:
|
|
||||||
print(f"\n{fmt_msg(data)}", flush=True)
|
|
||||||
else:
|
|
||||||
print(f"\n[SERVER] {json.dumps(data, indent=2)}", flush=True)
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
print(f"\n[SERVER] {raw}", flush=True)
|
|
||||||
|
|
||||||
async def sender(ws):
|
|
||||||
while True:
|
|
||||||
msg = await send_queue.get()
|
|
||||||
if msg is None:
|
|
||||||
break
|
|
||||||
await ws.send(msg)
|
|
||||||
|
|
||||||
async def run():
|
|
||||||
global send_queue
|
|
||||||
send_queue = asyncio.Queue()
|
|
||||||
|
|
||||||
input_thread = threading.Thread(target=input_loop, daemon=True)
|
|
||||||
input_thread_started = False
|
|
||||||
|
|
||||||
while not shutdown_event.is_set():
|
|
||||||
try:
|
|
||||||
async with websockets.connect(WS_URI) as ws:
|
|
||||||
print(f"connected to {WS_URI}")
|
|
||||||
if not input_thread_started:
|
|
||||||
print("Alt+Enter = newline | Enter = send | /help | Ctrl+C = quit\n")
|
|
||||||
input_thread.start()
|
|
||||||
input_thread_started = True
|
|
||||||
if token:
|
|
||||||
await ws.send(json.dumps({"token": token}))
|
|
||||||
|
|
||||||
recv_task = asyncio.create_task(receiver(ws))
|
|
||||||
send_task = asyncio.create_task(sender(ws))
|
|
||||||
shutdown_task = asyncio.create_task(shutdown_event.wait())
|
|
||||||
|
|
||||||
done, pending = await asyncio.wait(
|
|
||||||
[recv_task, send_task, shutdown_task],
|
|
||||||
return_when=asyncio.FIRST_COMPLETED,
|
|
||||||
)
|
|
||||||
for t in pending:
|
|
||||||
t.cancel()
|
|
||||||
|
|
||||||
if shutdown_event.is_set():
|
|
||||||
return
|
|
||||||
|
|
||||||
send_queue = asyncio.Queue()
|
|
||||||
print(f"\n[disconnected] reconnecting in {RETRY_DELAY}s…")
|
|
||||||
|
|
||||||
except (OSError, websockets.exceptions.WebSocketException):
|
|
||||||
if shutdown_event.is_set():
|
|
||||||
return
|
|
||||||
print(f"[waiting for server] retrying in {RETRY_DELAY}s…", flush=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
await asyncio.wait_for(shutdown_event.wait(), timeout=RETRY_DELAY)
|
|
||||||
except asyncio.TimeoutError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# ── input loop ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def input_loop():
|
|
||||||
session = PromptSession(key_bindings=bindings, multiline=True)
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
text = session.prompt(">>> ").strip()
|
|
||||||
if not text:
|
|
||||||
continue
|
|
||||||
if text == "/help":
|
|
||||||
print(HELP)
|
|
||||||
continue
|
|
||||||
parts = text.split()
|
|
||||||
cmd = parts[0]
|
|
||||||
if cmd in COMMANDS:
|
|
||||||
COMMANDS[cmd](parts[1:])
|
|
||||||
else:
|
|
||||||
asyncio.run_coroutine_threadsafe(send_queue.put(text), loop)
|
|
||||||
except (EOFError, KeyboardInterrupt):
|
|
||||||
asyncio.run_coroutine_threadsafe(shutdown_event.set(), loop)
|
|
||||||
break
|
|
||||||
|
|
||||||
# ── main ──────────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
def main():
|
|
||||||
global loop, shutdown_event
|
|
||||||
loop = asyncio.new_event_loop()
|
|
||||||
asyncio.set_event_loop(loop)
|
|
||||||
shutdown_event = asyncio.Event()
|
|
||||||
try:
|
|
||||||
loop.run_until_complete(run())
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
loop.close()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@@ -48,6 +48,7 @@ func main() {
|
|||||||
http.HandleFunc("POST /connection/deelevate", withCORS(httpRequest.HandleUserDeElevateConnection))
|
http.HandleFunc("POST /connection/deelevate", withCORS(httpRequest.HandleUserDeElevateConnection))
|
||||||
http.HandleFunc("GET /connections", withCORS(httpRequest.HandleUserGetConnections))
|
http.HandleFunc("GET /connections", withCORS(httpRequest.HandleUserGetConnections))
|
||||||
http.HandleFunc("GET /connection/messages", withCORS(httpRequest.HandleUserGetConnectionMessages))
|
http.HandleFunc("GET /connection/messages", withCORS(httpRequest.HandleUserGetConnectionMessages))
|
||||||
|
http.HandleFunc("GET /connections/unreadmessages", withCORS(httpRequest.HandleUserGetConnectionsUnreadMessages))
|
||||||
|
|
||||||
http.HandleFunc("POST /file", withCORS(httpRequest.HandleAttachmentFileUpload))
|
http.HandleFunc("POST /file", withCORS(httpRequest.HandleAttachmentFileUpload))
|
||||||
http.HandleFunc("GET /file", withCORS(httpRequest.HandleAttachmentFileDownload))
|
http.HandleFunc("GET /file", withCORS(httpRequest.HandleAttachmentFileDownload))
|
||||||
|
|||||||
Vendored
+41
-7
@@ -12,9 +12,10 @@ import (
|
|||||||
var (
|
var (
|
||||||
Mu sync.RWMutex
|
Mu sync.RWMutex
|
||||||
Users = make(map[uuid.UUID]*types.User)
|
Users = make(map[uuid.UUID]*types.User)
|
||||||
|
connectionsUnreadMessages = make(map[uuid.UUID]map[uuid.UUID]uint32)
|
||||||
)
|
)
|
||||||
|
|
||||||
func CacheGetUserById(id uuid.UUID) (*types.User, error) {
|
func GetUserById(id uuid.UUID) (*types.User, error) {
|
||||||
Mu.RLock()
|
Mu.RLock()
|
||||||
defer Mu.RUnlock()
|
defer Mu.RUnlock()
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ func CacheGetUserById(id uuid.UUID) (*types.User, error) {
|
|||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CacheGetUserByName(name string) (*types.User, error) {
|
func GetUserByName(name string) (*types.User, error) {
|
||||||
Mu.RLock()
|
Mu.RLock()
|
||||||
defer Mu.RUnlock()
|
defer Mu.RUnlock()
|
||||||
|
|
||||||
@@ -37,21 +38,21 @@ func CacheGetUserByName(name string) (*types.User, error) {
|
|||||||
return nil, fmt.Errorf("user %s not found", name)
|
return nil, fmt.Errorf("user %s not found", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CacheSaveUser(user *types.User) {
|
func SaveUser(user *types.User) {
|
||||||
Mu.Lock()
|
Mu.Lock()
|
||||||
defer Mu.Unlock()
|
defer Mu.Unlock()
|
||||||
|
|
||||||
Users[user.Id] = user
|
Users[user.Id] = user
|
||||||
}
|
}
|
||||||
|
|
||||||
func CacheDeleteUser(id uuid.UUID) {
|
func DeleteUser(id uuid.UUID) {
|
||||||
Mu.Lock()
|
Mu.Lock()
|
||||||
defer Mu.Unlock()
|
defer Mu.Unlock()
|
||||||
|
|
||||||
delete(Users, id)
|
delete(Users, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CacheAddConnection(a, b *types.User, conn *types.Connection) {
|
func AddConnection(a, b *types.User, conn *types.Connection) {
|
||||||
first, second := a, b
|
first, second := a, b
|
||||||
if a.Id.String() > b.Id.String() {
|
if a.Id.String() > b.Id.String() {
|
||||||
first, second = b, a
|
first, second = b, a
|
||||||
@@ -64,7 +65,7 @@ func CacheAddConnection(a, b *types.User, conn *types.Connection) {
|
|||||||
first.Mu.Unlock()
|
first.Mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func CacheDeleteConnection(a, b *types.User, id uuid.UUID) {
|
func DeleteConnection(a, b *types.User, id uuid.UUID) {
|
||||||
first, second := a, b
|
first, second := a, b
|
||||||
if a.Id.String() > b.Id.String() {
|
if a.Id.String() > b.Id.String() {
|
||||||
first, second = b, a
|
first, second = b, a
|
||||||
@@ -77,9 +78,42 @@ func CacheDeleteConnection(a, b *types.User, id uuid.UUID) {
|
|||||||
first.Mu.Unlock()
|
first.Mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func CacheGetConnection(user *types.User, id uuid.UUID) (*types.Connection, bool) {
|
func GetConnection(user *types.User, id uuid.UUID) (*types.Connection, bool) {
|
||||||
user.Mu.RLock()
|
user.Mu.RLock()
|
||||||
defer user.Mu.RUnlock()
|
defer user.Mu.RUnlock()
|
||||||
conn, ok := user.Connections[id]
|
conn, ok := user.Connections[id]
|
||||||
return conn, ok
|
return conn, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IncrementConnectionsUnreadMessages(userId uuid.UUID, connId uuid.UUID) {
|
||||||
|
Mu.Lock()
|
||||||
|
defer Mu.Unlock()
|
||||||
|
|
||||||
|
if _, ok := connectionsUnreadMessages[connId]; !ok {
|
||||||
|
connectionsUnreadMessages[connId] = make(map[uuid.UUID]uint32)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := connectionsUnreadMessages[connId][userId]; !ok {
|
||||||
|
connectionsUnreadMessages[connId][userId] = 0
|
||||||
|
}
|
||||||
|
connectionsUnreadMessages[connId][userId]++
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeallocateConnectionsUnreadMessages(userId uuid.UUID, connId uuid.UUID) {
|
||||||
|
Mu.Lock()
|
||||||
|
defer Mu.Unlock()
|
||||||
|
|
||||||
|
if _, ok := connectionsUnreadMessages[connId]; ok {
|
||||||
|
delete(connectionsUnreadMessages[connId], userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConnectionsUnreadMessages(userId uuid.UUID, connId uuid.UUID) (uint32, bool) {
|
||||||
|
Mu.RLock()
|
||||||
|
defer Mu.RUnlock()
|
||||||
|
|
||||||
|
if _, ok := connectionsUnreadMessages[connId]; !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return connectionsUnreadMessages[connId][userId], true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package convertions
|
package convertions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -40,10 +41,30 @@ func Uint32ToRgba(v uint32) *types.Rgba {
|
|||||||
return &types.Rgba{uint8(v >> 24), uint8(v >> 16), uint8(v >> 8), uint8(v)}
|
return &types.Rgba{uint8(v >> 24), uint8(v >> 16), uint8(v >> 8), uint8(v)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertStringUuid(str string) (uuid.UUID, error) {
|
func StringToUuid(str string) (uuid.UUID, error) {
|
||||||
return uuid.Parse(str)
|
return uuid.Parse(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertStringTimestamp(str string) (time.Time, error) {
|
func StringToUuidSlice(uuidStr string) (*[]uuid.UUID, error) {
|
||||||
|
if uuidStr == "" {
|
||||||
|
return nil, errors.New("empty string")
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(uuidStr, ",")
|
||||||
|
|
||||||
|
slice := make([]uuid.UUID, len(parts))
|
||||||
|
|
||||||
|
for _, part := range parts {
|
||||||
|
id, err := StringToUuid(part)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
slice = append(slice, id)
|
||||||
|
}
|
||||||
|
return &slice, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringToTimestamp(str string) (time.Time, error) {
|
||||||
return time.Parse(time.RFC3339, str)
|
return time.Parse(time.RFC3339, str)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ const (
|
|||||||
MaxDirectMsgCache uint32 = 32
|
MaxDirectMsgCache uint32 = 32
|
||||||
MaxHubMsgCache
|
MaxHubMsgCache
|
||||||
FileStorageBucketName string = "communicator"
|
FileStorageBucketName string = "communicator"
|
||||||
MaxPostBytes uint32 = 4 << 10
|
MaxRequestBytes uint32 = 4 << 10
|
||||||
MaxPostWithFileBytes uint32 = 1 << 30
|
MaxRequestWithFileBytes uint32 = 1 << 30
|
||||||
MaxPostWithAvatar uint = 1 << 20
|
MaxRequestWithAvatarBytes uint = 1 << 20
|
||||||
MaxPostWithProfileBg uint = 4 << 20
|
MaxRequestWithProfileBgBytes uint = 4 << 20
|
||||||
FileProcessingPartSize uint64 = 12 << 20
|
FileProcessingPartBytes uint64 = 12 << 20
|
||||||
FileProcessingThreads uint = 3
|
FileProcessingThreads uint = 3
|
||||||
FileDownloadLinkTtl time.Duration = 24 * time.Hour
|
FileDownloadLinkTtl time.Duration = 24 * time.Hour
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func HandleDm(response http.ResponseWriter, request *http.Request) {
|
func HandleDm(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,10 +74,14 @@ func HandleDm(response http.ResponseWriter, request *http.Request) {
|
|||||||
Receiver: conn.Id,
|
Receiver: conn.Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if user.WsConn != nil {
|
||||||
wsServer.WsSendMessageCloseIfTimeout(target, types.WsEventMessage{
|
wsServer.WsSendMessageCloseIfTimeout(target, types.WsEventMessage{
|
||||||
Type: WsEventType.DirectMessage,
|
Type: WsEventType.DirectMessage,
|
||||||
Event: message,
|
Event: message,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
cache.IncrementConnectionsUnreadMessages(user.Id, conn.Id)
|
||||||
|
}
|
||||||
|
|
||||||
err = postgresql.ConnectionMessageSave(ctx, message)
|
err = postgresql.ConnectionMessageSave(ctx, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,8 +92,52 @@ func HandleDm(response http.ResponseWriter, request *http.Request) {
|
|||||||
response.WriteHeader(http.StatusAccepted)
|
response.WriteHeader(http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HandleUserGetConnectionsUnreadMessages(response http.ResponseWriter, request *http.Request) {
|
||||||
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := request.Context()
|
||||||
|
user, err := getUserByToken(ctx, request.Header.Get("token"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionIds, err := convertions.StringToUuidSlice(request.URL.Query().Get("connections"))
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "invalid uuid format", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]uint32, len(*connectionIds))
|
||||||
|
|
||||||
|
for _, connId := range *connectionIds {
|
||||||
|
_, ok := cache.GetConnection(user, connId)
|
||||||
|
if !ok {
|
||||||
|
http.Error(response, "no such connection: "+connId.String(), http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, connId := range *connectionIds {
|
||||||
|
count, _ := cache.GetConnectionsUnreadMessages(user.Id, connId)
|
||||||
|
cache.DeallocateConnectionsUnreadMessages(user.Id, connId)
|
||||||
|
result = append(result, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
json, err := json2.Marshal(result)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.WriteHeader(http.StatusAccepted)
|
||||||
|
response.Write(json)
|
||||||
|
}
|
||||||
|
|
||||||
func HandleUserGetConnectionMessages(response http.ResponseWriter, request *http.Request) {
|
func HandleUserGetConnectionMessages(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -104,7 +152,7 @@ func HandleUserGetConnectionMessages(response http.ResponseWriter, request *http
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
before, err := convertions.ConvertStringTimestamp(request.URL.Query().Get("before"))
|
before, err := convertions.StringToTimestamp(request.URL.Query().Get("before"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
before = time.Now()
|
before = time.Now()
|
||||||
}
|
}
|
||||||
@@ -158,7 +206,7 @@ func HandleUserGetConnectionMessages(response http.ResponseWriter, request *http
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserNewConnection(response http.ResponseWriter, request *http.Request) {
|
func HandleUserNewConnection(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -167,7 +215,7 @@ func HandleUserNewConnection(response http.ResponseWriter, request *http.Request
|
|||||||
http.Error(response, "invalid token", http.StatusUnauthorized)
|
http.Error(response, "invalid token", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
recipientId, err := convertions.ConvertStringUuid(request.FormValue("recipient"))
|
recipientId, err := convertions.StringToUuid(request.FormValue("recipient"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(response, "no such user", http.StatusUnauthorized)
|
http.Error(response, "no such user", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
@@ -205,7 +253,7 @@ func HandleUserNewConnection(response http.ResponseWriter, request *http.Request
|
|||||||
http.Error(response, "internal server error", http.StatusInternalServerError)
|
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cache.CacheAddConnection(requestor, recipient, connection)
|
cache.AddConnection(requestor, recipient, connection)
|
||||||
|
|
||||||
wsServer.WsSendMessageCloseIfTimeout(recipient, types.WsEventMessage{
|
wsServer.WsSendMessageCloseIfTimeout(recipient, types.WsEventMessage{
|
||||||
Type: WsEventType.ConnectionCreated,
|
Type: WsEventType.ConnectionCreated,
|
||||||
@@ -217,7 +265,7 @@ func HandleUserNewConnection(response http.ResponseWriter, request *http.Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserDeleteConnection(response http.ResponseWriter, request *http.Request) {
|
func HandleUserDeleteConnection(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -259,7 +307,7 @@ func HandleUserDeleteConnection(response http.ResponseWriter, request *http.Requ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.CacheDeleteConnection(user, user2, conn.Id)
|
cache.DeleteConnection(user, user2, conn.Id)
|
||||||
wsServer.WsSendMessageCloseIfTimeout(user2, types.WsEventMessage{
|
wsServer.WsSendMessageCloseIfTimeout(user2, types.WsEventMessage{
|
||||||
Type: WsEventType.ConnectionDeleted,
|
Type: WsEventType.ConnectionDeleted,
|
||||||
Event: conn.Id,
|
Event: conn.Id,
|
||||||
@@ -270,7 +318,7 @@ func HandleUserDeleteConnection(response http.ResponseWriter, request *http.Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserElevateConnection(response http.ResponseWriter, request *http.Request) {
|
func HandleUserElevateConnection(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -330,7 +378,7 @@ func HandleUserElevateConnection(response http.ResponseWriter, request *http.Req
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserDeElevateConnection(response http.ResponseWriter, request *http.Request) {
|
func HandleUserDeElevateConnection(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +425,7 @@ func HandleUserDeElevateConnection(response http.ResponseWriter, request *http.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserGetConnections(response http.ResponseWriter, request *http.Request) {
|
func HandleUserGetConnections(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func HandleAttachmentFileUpload(response http.ResponseWriter, request *http.Request) {
|
func HandleAttachmentFileUpload(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postFile) {
|
if !validCheckWithResponseOnFail(&response, request, file) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -22,9 +22,9 @@ func HandleAttachmentFileUpload(response http.ResponseWriter, request *http.Requ
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Body = http.MaxBytesReader(response, request.Body, int64(globals.MaxPostWithFileBytes))
|
request.Body = http.MaxBytesReader(response, request.Body, int64(globals.MaxRequestWithFileBytes))
|
||||||
|
|
||||||
if err = request.ParseMultipartForm(int64(globals.MaxPostBytes)); err != nil {
|
if err = request.ParseMultipartForm(int64(globals.MaxRequestBytes)); err != nil {
|
||||||
http.Error(response, "invalid multipart form", http.StatusBadRequest)
|
http.Error(response, "invalid multipart form", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ func HandleAttachmentFileUpload(response http.ResponseWriter, request *http.Requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleGetUserAvatar(response http.ResponseWriter, request *http.Request) {
|
func HandleGetUserAvatar(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -72,7 +72,7 @@ func HandleGetUserAvatar(response http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
targetId, err := convertions.ConvertStringUuid(request.URL.Query().Get("userid"))
|
targetId, err := convertions.StringToUuid(request.URL.Query().Get("userid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(response, "invalid userid", http.StatusBadRequest)
|
http.Error(response, "invalid userid", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@@ -100,7 +100,7 @@ func HandleGetUserAvatar(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleGetUserProfileBg(response http.ResponseWriter, request *http.Request) {
|
func HandleGetUserProfileBg(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -110,7 +110,7 @@ func HandleGetUserProfileBg(response http.ResponseWriter, request *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
targetId, err := convertions.ConvertStringUuid(request.URL.Query().Get("userid"))
|
targetId, err := convertions.StringToUuid(request.URL.Query().Get("userid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(response, "invalid userid", http.StatusBadRequest)
|
http.Error(response, "invalid userid", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@@ -138,7 +138,7 @@ func HandleGetUserProfileBg(response http.ResponseWriter, request *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleAttachmentFileDownload(response http.ResponseWriter, request *http.Request) {
|
func HandleAttachmentFileDownload(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func getUserById(ctx context.Context, userId uuid.UUID) (*types.User, error) {
|
func getUserById(ctx context.Context, userId uuid.UUID) (*types.User, error) {
|
||||||
user, err := cache.CacheGetUserById(userId)
|
user, err := cache.GetUserById(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
user = &types.User{Id: userId}
|
user = &types.User{Id: userId}
|
||||||
err = postgresql.GetWholeUser(ctx, user)
|
err = postgresql.GetWholeUser(ctx, user)
|
||||||
@@ -35,12 +35,12 @@ func getUserByToken(ctx context.Context, token string) (*types.User, error) {
|
|||||||
return getUserById(ctx, userId)
|
return getUserById(ctx, userId)
|
||||||
}
|
}
|
||||||
func getConnectionWithResponseOnFail(response *http.ResponseWriter, request *http.Request, user *types.User) (*types.Connection, bool) {
|
func getConnectionWithResponseOnFail(response *http.ResponseWriter, request *http.Request, user *types.User) (*types.Connection, bool) {
|
||||||
connectionId, err := convertions.ConvertStringUuid(request.FormValue("connectionid"))
|
connectionId, err := convertions.StringToUuid(request.FormValue("connectionid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(*response, "invalid connectionid", http.StatusBadRequest)
|
http.Error(*response, "invalid connectionid", http.StatusBadRequest)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
conn, ok := cache.CacheGetConnection(user, connectionId)
|
conn, ok := cache.GetConnection(user, connectionId)
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(*response, "invalid connectionid", http.StatusBadRequest)
|
http.Error(*response, "invalid connectionid", http.StatusBadRequest)
|
||||||
return nil, false
|
return nil, false
|
||||||
|
|||||||
@@ -11,23 +11,23 @@ import (
|
|||||||
type postType uint8
|
type postType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
postNormal postType = iota
|
normal postType = iota
|
||||||
postFile
|
file
|
||||||
postAvatar
|
avatar
|
||||||
postProfileBg
|
profileBg
|
||||||
)
|
)
|
||||||
|
|
||||||
func validCheckWithResponseOnFail(response *http.ResponseWriter, request *http.Request, pt postType) bool {
|
func validCheckWithResponseOnFail(response *http.ResponseWriter, request *http.Request, pt postType) bool {
|
||||||
var maxSize int64
|
var maxSize int64
|
||||||
switch pt {
|
switch pt {
|
||||||
case postFile:
|
case file:
|
||||||
maxSize = int64(globals.MaxPostWithFileBytes)
|
maxSize = int64(globals.MaxRequestWithFileBytes)
|
||||||
case postAvatar:
|
case avatar:
|
||||||
maxSize = int64(globals.MaxPostWithAvatar)
|
maxSize = int64(globals.MaxRequestWithAvatarBytes)
|
||||||
case postProfileBg:
|
case profileBg:
|
||||||
maxSize = int64(globals.MaxPostWithProfileBg)
|
maxSize = int64(globals.MaxRequestWithProfileBgBytes)
|
||||||
default:
|
default:
|
||||||
maxSize = int64(globals.MaxPostBytes)
|
maxSize = int64(globals.MaxRequestBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.ContentLength > maxSize {
|
if request.ContentLength > maxSize {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func HandleUserNewToken(response http.ResponseWriter, request *http.Request) {
|
func HandleUserNewToken(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ func HandleUserNewToken(response http.ResponseWriter, request *http.Request) {
|
|||||||
ctx = request.Context()
|
ctx = request.Context()
|
||||||
)
|
)
|
||||||
|
|
||||||
user, err = cache.CacheGetUserByName(username)
|
user, err = cache.GetUserByName(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
user = &types.User{Name: username}
|
user = &types.User{Name: username}
|
||||||
if err = postgresql.UserGetStandardInfoByName(ctx, user); err != nil {
|
if err = postgresql.UserGetStandardInfoByName(ctx, user); err != nil {
|
||||||
@@ -78,7 +78,7 @@ func HandleUserNewToken(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserNew(response http.ResponseWriter, request *http.Request) {
|
func HandleUserNew(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ func HandleUserNew(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserDelete(response http.ResponseWriter, request *http.Request) {
|
func HandleUserDelete(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -136,12 +136,12 @@ func HandleUserDelete(response http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.CacheDeleteUser(userId)
|
cache.DeleteUser(userId)
|
||||||
response.WriteHeader(http.StatusAccepted)
|
response.WriteHeader(http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserModProfile(response http.ResponseWriter, request *http.Request) {
|
func HandleUserModProfile(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ func HandleUserModProfile(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserModAvatar(response http.ResponseWriter, request *http.Request) {
|
func HandleUserModAvatar(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postAvatar) {
|
if !validCheckWithResponseOnFail(&response, request, avatar) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -202,9 +202,9 @@ func HandleUserModAvatar(response http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Body = http.MaxBytesReader(response, request.Body, int64(globals.MaxPostWithAvatar))
|
request.Body = http.MaxBytesReader(response, request.Body, int64(globals.MaxRequestWithAvatarBytes))
|
||||||
|
|
||||||
if err = request.ParseMultipartForm(int64(globals.MaxPostBytes)); err != nil {
|
if err = request.ParseMultipartForm(int64(globals.MaxRequestBytes)); err != nil {
|
||||||
http.Error(response, "invalid multipart form", http.StatusBadRequest)
|
http.Error(response, "invalid multipart form", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -254,7 +254,7 @@ func HandleUserModAvatar(response http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserModProfileBg(response http.ResponseWriter, request *http.Request) {
|
func HandleUserModProfileBg(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postProfileBg) {
|
if !validCheckWithResponseOnFail(&response, request, profileBg) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -265,9 +265,9 @@ func HandleUserModProfileBg(response http.ResponseWriter, request *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Body = http.MaxBytesReader(response, request.Body, int64(globals.MaxPostWithProfileBg))
|
request.Body = http.MaxBytesReader(response, request.Body, int64(globals.MaxRequestWithProfileBgBytes))
|
||||||
|
|
||||||
if err = request.ParseMultipartForm(int64(globals.MaxPostBytes)); err != nil {
|
if err = request.ParseMultipartForm(int64(globals.MaxRequestBytes)); err != nil {
|
||||||
http.Error(response, "invalid multipart form", http.StatusBadRequest)
|
http.Error(response, "invalid multipart form", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -317,7 +317,7 @@ func HandleUserModProfileBg(response http.ResponseWriter, request *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func HandleUserGetUser(response http.ResponseWriter, request *http.Request) {
|
func HandleUserGetUser(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(&response, request, postNormal) {
|
if !validCheckWithResponseOnFail(&response, request, normal) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := request.Context()
|
ctx := request.Context()
|
||||||
@@ -328,7 +328,7 @@ func HandleUserGetUser(response http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
targetId, err := convertions.ConvertStringUuid(request.URL.Query().Get("targetid"))
|
targetId, err := convertions.StringToUuid(request.URL.Query().Get("targetid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(response, "invalid userid", http.StatusUnauthorized)
|
http.Error(response, "invalid userid", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func Init(ctx context.Context) {
|
|||||||
func Upload(ctx context.Context, key string, body io.Reader, size int64, contentType string, metadata map[string]string) error {
|
func Upload(ctx context.Context, key string, body io.Reader, size int64, contentType string, metadata map[string]string) error {
|
||||||
opt := minio.PutObjectOptions{
|
opt := minio.PutObjectOptions{
|
||||||
ContentType: contentType,
|
ContentType: contentType,
|
||||||
PartSize: globals.FileProcessingPartSize,
|
PartSize: globals.FileProcessingPartBytes,
|
||||||
NumThreads: globals.FileProcessingThreads,
|
NumThreads: globals.FileProcessingThreads,
|
||||||
UserMetadata: metadata,
|
UserMetadata: metadata,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ func GetWholeUser(ctx context.Context, user *types.User) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.CacheSaveUser(user)
|
cache.SaveUser(user)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func handleUnauthenticatedMessage(ctx context.Context, user *types.User, userMes
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
userFromCache, err := cache.CacheGetUserById(userId)
|
userFromCache, err := cache.GetUserById(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Event = types.WsAuthMessage{
|
response.Event = types.WsAuthMessage{
|
||||||
Success: false,
|
Success: false,
|
||||||
@@ -138,7 +138,7 @@ func handleUnauthenticatedMessage(ctx context.Context, user *types.User, userMes
|
|||||||
|
|
||||||
func closeConnection(user *types.User, ignoreCache bool) {
|
func closeConnection(user *types.User, ignoreCache bool) {
|
||||||
if !ignoreCache {
|
if !ignoreCache {
|
||||||
cache.CacheDeleteUser(user.Id)
|
cache.DeleteUser(user.Id)
|
||||||
}
|
}
|
||||||
if user.WsConn != nil {
|
if user.WsConn != nil {
|
||||||
user.WsConn.CloseNow()
|
user.WsConn.CloseNow()
|
||||||
|
|||||||
Reference in New Issue
Block a user