friends
This commit is contained in:
parent
049cb43264
commit
eb5f473de0
59
README.md
59
README.md
@ -287,3 +287,62 @@ client:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**friend request**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "friend_request",
|
||||||
|
"data" : {
|
||||||
|
"user": "<friend>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "friend_request_response",
|
||||||
|
"data": {
|
||||||
|
"success": <true|false>
|
||||||
|
"msg": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**unfriend**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "unfriend_request",
|
||||||
|
"data" : {
|
||||||
|
"user": "<friend>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
response:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "unfriend_request_response",
|
||||||
|
"data": {
|
||||||
|
"success": <true|false>
|
||||||
|
"msg": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**friend update**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "friends_update",
|
||||||
|
"data": {
|
||||||
|
"friends": "<list of friends>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -131,6 +131,7 @@ class ConnectionHandler(object):
|
|||||||
"msg": ""
|
"msg": ""
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
await self.send_friends(conn)
|
||||||
await self._on_match_state_req(conn, None)
|
await self._on_match_state_req(conn, None)
|
||||||
return conn
|
return conn
|
||||||
await conn.send(json.dumps({
|
await conn.send(json.dumps({
|
||||||
@ -231,6 +232,7 @@ class ConnectionHandler(object):
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
|
await self.send_friends(conn)
|
||||||
await self._on_match_state_req(conn, None)
|
await self._on_match_state_req(conn, None)
|
||||||
|
|
||||||
return conn
|
return conn
|
||||||
@ -337,6 +339,35 @@ class ConnectionHandler(object):
|
|||||||
try:
|
try:
|
||||||
if len(opponent) <= 16 and '\'' not in opponent and '"' not in opponent:
|
if len(opponent) <= 16 and '\'' not in opponent and '"' not in opponent:
|
||||||
if len(self.user_manager.get_user(opponent)) > 0:
|
if len(self.user_manager.get_user(opponent)) > 0:
|
||||||
|
|
||||||
|
if len(self.match_manager.get_matches_for_user(conn.user_name)) >= 5:
|
||||||
|
await conn.websocket.send(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"type": "match_request_response",
|
||||||
|
"data": {
|
||||||
|
"success": False,
|
||||||
|
"msg": "player " + opponent + " has too many open matches"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (self.match_manager.is_match(conn.user_name, opponent)):
|
||||||
|
await conn.websocket.send(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"type": "match_request_response",
|
||||||
|
"data": {
|
||||||
|
"success": False,
|
||||||
|
"msg": "you are already plaing against " + opponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
await self._start_match(conn.user_name, opponent)
|
await self._start_match(conn.user_name, opponent)
|
||||||
|
|
||||||
await conn.websocket.send(
|
await conn.websocket.send(
|
||||||
@ -461,13 +492,88 @@ class ConnectionHandler(object):
|
|||||||
if match is not None:
|
if match is not None:
|
||||||
match_state = match.to_json_state()
|
match_state = match.to_json_state()
|
||||||
|
|
||||||
conn.send(json.dumps({
|
await conn.send(json.dumps({
|
||||||
'type': 'match_update',
|
'type': 'match_update',
|
||||||
'data': {
|
'data': {
|
||||||
'match_state': json.loads(match_state)
|
'match_state': json.loads(match_state)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
async def _on_friend_request(self, conn, data):
|
||||||
|
msg = "error in handling friend request"
|
||||||
|
success = False
|
||||||
|
try:
|
||||||
|
friend = data['user'].lower()
|
||||||
|
|
||||||
|
# check for user:
|
||||||
|
if "\"" not in friend and "'" not in friend and ";" not in friend:
|
||||||
|
if friend in self.user_manager.get_friends_for_user(conn.user_name):
|
||||||
|
success = False
|
||||||
|
msg = f"'{friend}' is already your friend"
|
||||||
|
|
||||||
|
elif self.user_manager.add_friend_to_user(conn.user_name, friend):
|
||||||
|
success = True
|
||||||
|
msg = f"added '{friend}' as a friend"
|
||||||
|
|
||||||
|
else:
|
||||||
|
success = False
|
||||||
|
msg = f"player '{friend}' not found"
|
||||||
|
|
||||||
|
else:
|
||||||
|
success = False
|
||||||
|
msg = "misformated friend request"
|
||||||
|
|
||||||
|
finally:
|
||||||
|
await conn.send(json.dumps({
|
||||||
|
'type': 'friend_request_response',
|
||||||
|
'data': {
|
||||||
|
'success': success,
|
||||||
|
'msg': msg
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
if success:
|
||||||
|
await self.send_friends(conn)
|
||||||
|
|
||||||
|
async def _on_unfriend_request(self, conn, data):
|
||||||
|
success = False
|
||||||
|
msg = "error in handling unfriend request"
|
||||||
|
try:
|
||||||
|
friend = data['user'].lower()
|
||||||
|
|
||||||
|
if "\"" not in friend and "'" not in friend and ";" not in friend:
|
||||||
|
if friend not in self.user_manager.get_friends_for_user(conn.user_name):
|
||||||
|
success = False
|
||||||
|
msg = f"cannot end friendship with '{friend}': it's not one of your friends"
|
||||||
|
else:
|
||||||
|
self.user_manager.remove_friend_from_user(
|
||||||
|
conn.user_name, friend)
|
||||||
|
|
||||||
|
success = True
|
||||||
|
msg = f"removed '{friend}' from your friend list"
|
||||||
|
|
||||||
|
finally:
|
||||||
|
await conn.send(json.dumps({
|
||||||
|
'type': 'unfriend_request_response',
|
||||||
|
'data': {
|
||||||
|
'success': success,
|
||||||
|
'msg': msg
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
if success:
|
||||||
|
await self.send_friends(conn)
|
||||||
|
|
||||||
|
async def send_friends(self, conn):
|
||||||
|
friends = list(self.user_manager.get_friends_for_user(conn.user_name))
|
||||||
|
|
||||||
|
await conn.send(json.dumps({
|
||||||
|
'type': 'friends_update',
|
||||||
|
'data': {
|
||||||
|
'friends': friends
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
async def disconnect(self, conn):
|
async def disconnect(self, conn):
|
||||||
self._del_connection(conn)
|
self._del_connection(conn)
|
||||||
|
|
||||||
@ -494,5 +600,11 @@ class ConnectionHandler(object):
|
|||||||
elif t == "match_states_request":
|
elif t == "match_states_request":
|
||||||
await self._on_match_state_req(conn, msg['data'])
|
await self._on_match_state_req(conn, msg['data'])
|
||||||
|
|
||||||
|
elif t == "friend_request":
|
||||||
|
await self._on_friend_request(conn, msg['data'])
|
||||||
|
|
||||||
|
elif t == "unfriend_request":
|
||||||
|
await self._on_unfriend_request(conn, msg['data'])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("could not interpret message: " + msg_str)
|
print("could not interpret message: " + msg_str)
|
||||||
|
@ -18,9 +18,11 @@ def create_tables():
|
|||||||
"DROP TABLE IF EXISTS matches",
|
"DROP TABLE IF EXISTS matches",
|
||||||
"DROP TABLE IF EXISTS sessions",
|
"DROP TABLE IF EXISTS sessions",
|
||||||
"DROP TABLE IF EXISTS users",
|
"DROP TABLE IF EXISTS users",
|
||||||
|
"DROP TABLE IF EXISTS friends",
|
||||||
"CREATE TABLE users (name varchar(16) NOT NULL, pw_hash varchar(128) NOT NULL, pw_salt varchar(32) NOT NULL, last_seen datetime NOT NULL, PRIMARY KEY (name)) CHARACTER SET " + settings.db_charset,
|
"CREATE TABLE users (name varchar(16) NOT NULL, pw_hash varchar(128) NOT NULL, pw_salt varchar(32) NOT NULL, last_seen datetime NOT NULL, PRIMARY KEY (name)) CHARACTER SET " + settings.db_charset,
|
||||||
"CREATE TABLE matches (id varchar(32) NOT NULL, user_a varchar(16) NOT NULL, user_b varchar(16) NOT NULL, match_state varchar(4096) NOT NULL, active_user varchar(16), last_active datetime NOT NULL, FOREIGN KEY (user_a) REFERENCES users(name), FOREIGN KEY (user_b) REFERENCES users(name), FOREIGN KEY (active_user) REFERENCES users(name)) CHARACTER SET " + settings.db_charset,
|
"CREATE TABLE matches (id varchar(32) NOT NULL, user_a varchar(16) NOT NULL, user_b varchar(16) NOT NULL, match_state varchar(4096) NOT NULL, active_user varchar(16), last_active datetime NOT NULL, FOREIGN KEY (user_a) REFERENCES users(name), FOREIGN KEY (user_b) REFERENCES users(name), FOREIGN KEY (active_user) REFERENCES users(name)) CHARACTER SET " + settings.db_charset,
|
||||||
"CREATE TABLE sessions (id varchar(32) NOT NULL, registered_user varchar(16), temp_user varchar(16), last_seen datetime NOT NULL, PRIMARY KEY (id), FOREIGN KEY(registered_user) REFERENCES users(name)) CHARACTER SET " + settings.db_charset
|
"CREATE TABLE sessions (id varchar(32) NOT NULL, registered_user varchar(16), temp_user varchar(16), last_seen datetime NOT NULL, PRIMARY KEY (id), FOREIGN KEY(registered_user) REFERENCES users(name)) CHARACTER SET " + settings.db_charset,
|
||||||
|
"CREATE TABLE friends (user varchar(16) NOT NULL, friend varchar(16) NOT NULL, FOREIGN KEY(user) REFERENCES users(name), FOREIGN KEY(friend) REFERENCES users(name)) CHARACTER SET " + settings.db_charset
|
||||||
]
|
]
|
||||||
|
|
||||||
for query in queries:
|
for query in queries:
|
||||||
|
@ -54,6 +54,10 @@ class MatchManager(object):
|
|||||||
print("updated match")
|
print("updated match")
|
||||||
return match
|
return match
|
||||||
|
|
||||||
|
def is_match(self, player_a, player_b):
|
||||||
|
query = f"SELECT * FROM matches WHERE (user_a='{player_a}' AND user_b='{player_b}') OR (user_a='{player_b}' AND user_b='{player_a}')"
|
||||||
|
return len(DatabaseConnection.global_single_query(query))
|
||||||
|
|
||||||
def delete_match(self, match_id):
|
def delete_match(self, match_id):
|
||||||
query = f"DELETE FROM matches WHERE id='{match_id}'"
|
query = f"DELETE FROM matches WHERE id='{match_id}'"
|
||||||
DatabaseConnection.global_single_execution(query)
|
DatabaseConnection.global_single_execution(query)
|
||||||
|
@ -17,6 +17,13 @@ class UserManager(object):
|
|||||||
query = f"DELETE FROM users where name='{user_name}'"
|
query = f"DELETE FROM users where name='{user_name}'"
|
||||||
DatabaseConnection.global_single_execution(query)
|
DatabaseConnection.global_single_execution(query)
|
||||||
|
|
||||||
|
# remove from friends:
|
||||||
|
query = f"DELETE FROM friends WHERE user='{user_name}'"
|
||||||
|
DatabaseConnection.global_single_execution(query)
|
||||||
|
|
||||||
|
query = f"DELETE FROM friends WHERE friend='{user_name}'"
|
||||||
|
DatabaseConnection.global_single_execution(query)
|
||||||
|
|
||||||
def verify_user(self, user_name, pw):
|
def verify_user(self, user_name, pw):
|
||||||
query = f"SELECT * FROM users where name='{user_name}'"
|
query = f"SELECT * FROM users where name='{user_name}'"
|
||||||
users = DatabaseConnection.global_single_query(query)
|
users = DatabaseConnection.global_single_query(query)
|
||||||
@ -42,6 +49,25 @@ class UserManager(object):
|
|||||||
assert len(matches) == 1
|
assert len(matches) == 1
|
||||||
query = f"UPDATE users SET last_seen='{datetime.datetime.now()}' WHERE name='{user_name}'"
|
query = f"UPDATE users SET last_seen='{datetime.datetime.now()}' WHERE name='{user_name}'"
|
||||||
DatabaseConnection.global_single_execution(query)
|
DatabaseConnection.global_single_execution(query)
|
||||||
|
|
||||||
|
def add_friend_to_user(self, user_name, friend_name):
|
||||||
|
if len(self.get_user(friend_name)) > 0:
|
||||||
|
query = f"INSERT INTO friends (user, friend) VALUES ( '{user_name}', '{friend_name}')"
|
||||||
|
DatabaseConnection.global_single_execution(query)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_friends_for_user(self, user_name):
|
||||||
|
query = f"SELECT friend FROM friends WHERE user='{user_name}'"
|
||||||
|
tmp = DatabaseConnection.global_single_query(query)
|
||||||
|
friends = set()
|
||||||
|
for entry in tmp:
|
||||||
|
friends.add(entry['friend'])
|
||||||
|
return friends
|
||||||
|
|
||||||
|
def remove_friend_from_user(self, user_name, friend_name):
|
||||||
|
query = f"DELETE FROM friends WHERE user='{user_name}' AND friend='{friend_name}'"
|
||||||
|
DatabaseConnection.global_single_execution(query)
|
||||||
|
|
||||||
def get_all_users(self):
|
def get_all_users(self):
|
||||||
query = "SELECT name, last_seen FROM users"
|
query = "SELECT name, last_seen FROM users"
|
||||||
|
Loading…
Reference in New Issue
Block a user