Skip to content
This repository was archived by the owner on Dec 20, 2021. It is now read-only.

Commit 8b470ee

Browse files
committed
Basic WS Clients
Untested
1 parent 8dd39b3 commit 8b470ee

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

vrcpy/errors.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,11 @@ class NotFriendsError(Exception):
4141
class AlreadyFriendsError(Exception):
4242
## When users are already friends
4343
pass
44+
45+
class WebSocketError(Exception):
46+
## When ws dies
47+
pass
48+
49+
class WebSocketOpenedError(Exception):
50+
## When 2 websockets are attempted to be open
51+
pass

vrcpy/wss.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
from vrcpy import Client, AClient, objects, aobjects
2+
from vrcpy.errors import WebSocketError, WebSocketOpenedError
3+
import threading
4+
import asyncio
5+
import json
6+
7+
class __WSSClient:
8+
def __do_function(self, function, *args):
9+
if self.clientType == 0:
10+
function(*args)
11+
else:
12+
self.api.loop.create_task(function(*args))
13+
14+
def __ws_message(self, ws, message):
15+
message = json.loads(message)
16+
17+
switch = {
18+
"friend-location": self.__ws_friend_location,
19+
"friend-active": self.__ws_friend_active,
20+
"friend-offline": self.__ws_friend_offline
21+
}
22+
23+
if message["type"] in switch:
24+
self.__do_function(switch[message["type"]], json.loads(message["content"]))
25+
26+
def __ws_error(self, ws, error):
27+
raise WebSocketError(error)
28+
29+
def __ws_close(self, ws):
30+
self.wss = None
31+
self.__wssthread = None
32+
33+
def __ws_open(self, ws):
34+
pass
35+
36+
def __open_ws(self):
37+
if self.ws != None:
38+
raise WebSocketOpenedError("There is already a websocket open!")
39+
40+
if asyncio.iscoroutinefunction(self.api.call):
41+
for cookie in self.api.session.cookie_jar:
42+
if cookie.key == "auth":
43+
auth = cookie.value
44+
else:
45+
auth = self.api.session.cookies.get("auth")
46+
47+
self.ws = websocket.WebSocketApp(
48+
"wss://pipeline.vrchat.cloud/?authToken="+auth,
49+
on_message=self.__ws_message,
50+
on_error=self.__ws_error,
51+
on_close=self.__ws_close,
52+
on_open=self.__ws_open)
53+
54+
self.__wsthread = threading.Thread(target=ws.run_forever)
55+
self.__wsthread.daemon = True
56+
self.__wsthread.start()
57+
58+
class WSSClient(__WSSClient, Client):
59+
# User WS overwrites
60+
61+
def on_friend_active(self, friend):
62+
pass
63+
64+
def on_friend_offline(self, friend):
65+
pass
66+
67+
def on_friend_location(self, friend):
68+
pass
69+
70+
# WS handles
71+
72+
def __ws_friend_active(self, content):
73+
self.on_friend_active(objects.User(content))
74+
75+
def __ws_friend_location(self, content):
76+
#world = content["world"]
77+
#del content["world"]
78+
79+
self.on_friend_location(objects.User(content))
80+
81+
def __ws_friend_offline(self, content):
82+
self.on_friend_offline(self.fetch_user_by_id(content["userId"]))
83+
84+
# Internal Client overwrites
85+
86+
def login(self, username, password):
87+
Client.login(username, password)
88+
if self.loggedIn: self.__open_ws()
89+
90+
def login2fa(self, username, password, code=None, verify=False):
91+
Client.login2fa(username, password, code, verify)
92+
if self.loggedIn: self.__open_ws()
93+
94+
def verify2fa(self, code):
95+
Client.verify2fa(code)
96+
if self.loggedIn: self.__open_ws()
97+
98+
def logout(self):
99+
Client.logout()
100+
if not self.loggedIn: self.wss.close()
101+
102+
def __init__(self, verify=True):
103+
self.ws = None
104+
self.__wsthread = None
105+
self.clientType = 0
106+
107+
Client.__init__(verify, True) # Caching is always true for ws client
108+
109+
class AWSSClient(__WSSClient, AClient):
110+
# User WS overwrites
111+
112+
async def on_friend_active(self, friend):
113+
pass
114+
115+
async def on_friend_offline(self, friend):
116+
pass
117+
118+
async def on_friend_location(self, friend):
119+
pass
120+
121+
# WS handles
122+
123+
async def __ws_friend_active(self, content):
124+
self.on_friend_active(aobjects.User(content))
125+
126+
async def __ws_friend_location(self, content):
127+
#world = content["world"]
128+
#del content["world"]
129+
130+
self.on_friend_location(aobjects.User(content))
131+
132+
async def __ws_friend_offline(self, content):
133+
self.on_friend_offline(await self.fetch_user_by_id(content["userId"]))
134+
135+
# Internal Client overwrites
136+
137+
async def login(self, username, password):
138+
await AClient.login(username, password)
139+
if self.loggedIn: self.__open_ws()
140+
141+
async def login2fa(self, username, password, code=None, verify=False):
142+
await AClient.login2fa(username, password, code, verify)
143+
if self.loggedIn: self.__open_ws()
144+
145+
async def verify2fa(self, code):
146+
await AClient.verify2fa(code)
147+
if self.loggedIn: self.__open_ws()
148+
149+
async def logout(self):
150+
await AClient.logout()
151+
if not self.loggedIn: self.wss.close()
152+
153+
def __init__(self, verify=True):
154+
self.ws = None
155+
self.__wsthread = None
156+
self.clientType = 1
157+
158+
AClient.__init__(verify, True) # Caching is always true for ws client

0 commit comments

Comments
 (0)