Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 229 additions & 0 deletions smserver/chat_commands/general.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
""" General Chat command to handle """

from smserver import models
from smserver import smutils
from smserver.chatplugin import ChatPlugin
from smserver.chathelper import with_color


class ChatHelp(ChatPlugin):
Expand Down Expand Up @@ -75,3 +77,230 @@ def __call__(self, serv, message):

for user in serv.active_users:
user.chat_timestamp = serv.conn.chat_timestamp

class FriendNotifications(ChatPlugin):
command = "friendnotif"
helper = "Enable notifications whenever a friend gets on/off line. /friendnotif"

def __call__(self, serv, message):

for user in serv.active_users:
if user.friend_notifications:
user.friend_notifications = False
serv.send_message("Friend notifications disabled", to="me")
else:
user.friend_notifications = True
serv.send_message("Friend notifications enabled", to="me")

class AddFriend(ChatPlugin):
command = "addfriend"
helper = "Add a friend. /addfriend user"

def __call__(self, serv, message):
for user in serv.active_users:
if not user:
return
newfriend = serv.session.query(models.User).filter_by(name=message).first()
if not newfriend:
serv.send_message("Unknown user %s" % with_color(message), to="me")
return
if newfriend.name == user.name:
serv.send_message("Cant befriend yourself", to="me")
return
relationships = serv.session.query(models.Relationship).filter( \
((models.Relationship.user1_id == user.id) & (models.Relationship.user2_id == newfriend.id)) | \
(models.Relationship.user2_id == user.id) & (models.Relationship.user1_id == newfriend.id))
if not relationships.first():
serv.session.add(models.Relationship(user1_id = user.id, user2_id = newfriend.id, state = 0))
serv.send_message("Friend request sent to %s" % with_color(message), to="me")
else:
relationships = relationships.all()
if len(relationships) != 1:
if friendship[0].state == 2:
if friendship.user1_id == user.id:
Unignore.__call__(self, serv, message)
friendship = relationships[1]
if friendship[1].state == 2:
if friendship.user1_id == user.id:
Unignore.__call__(self, serv, message)
friendship = relationships[0]
else:
friendship = relationships[0]
if friendship.state == 1:
serv.send_message("%s is already friends with you" % with_color(message), to="me")
return
if friendship.state == 2:
serv.send_message("Cant send %s a friend request" % with_color(message), to="me")
return
if friendship.user1_id == user.id:
serv.send_message("Already sent a friend request to %s" % with_color(message), to="me")
return
friendship.state = 1
serv.send_message("Accepted friend request from %s" % with_color(message), to="me")
serv.session.commit()

class RemoveFriend(ChatPlugin):
command = "removefriend"
helper = "Remove a friend. /removefriend user"

def __call__(self, serv, message):
for user in serv.active_users:
if not user:
return
oldfriend = serv.session.query(models.User).filter_by(name=message).first()
if not oldfriend:
serv.send_message("Unknown user %s" % with_color(message), to="me")
return
friendship = serv.session.query(models.Relationship).filter( \
((models.Relationship.user1_id == user.id) & (models.Relationship.user2_id == oldfriend.id) & ((models.Relationship.state == 1) | (models.Relationship.state == 0))) | \
((models.Relationship.user2_id == user.id) & (models.Relationship.user1_id == oldfriend.id) & ((models.Relationship.state == 1) | (models.Relationship.state == 0))) )
friendships = friendship.first()
if not friendships:
serv.send_message("%s is not your friend" % with_color(message), to="me")
serv.session.delete(friendships)
serv.session.commit()
serv.send_message("%s is no longer your friend" % with_color(message), to="me")


class Ignore(ChatPlugin):
command = "ignore"
helper = "Ignore someone(Can't send friend requests or pm). /ignore user"

def __call__(self, serv, message):
for user in serv.active_users:
if not user:
return
newignore = serv.session.query(models.User).filter_by(name=message).first()
if not newignore:
serv.send_message("Unknown user %s" % with_color(message), to="me")
return
if newignore.name == user.name:
serv.send_message("Cant ignore yourself", to="me")
return
relationships = serv.session.query(models.Relationship).filter( \
((models.Relationship.user1_id == user.id) & (models.Relationship.user2_id == newignore.id)) | \
(models.Relationship.user2_id == user.id) & (models.Relationship.user1_id == newignore.id))
relationships = relationships.all()
ignored = False
for relationship in relationships:
if relationship.state == 0 or relationship.state == 1:
serv.session.delete(relationship)
serv.send_message("%s is no longer your friend" % with_color(message), to="me")
elif relationship.state == 2 and relationship.user1_id == user.id:
serv.send_message("%s is already ignored" % with_color(message), to="me")
ignored = True
if not ignored:
serv.session.add(models.Relationship(user1_id = user.id, user2_id = newignore.id, state = 2))
serv.send_message("%s ignored" % with_color(message), to="me")
serv.session.commit()



class Unignore(ChatPlugin):
command = "unignore"
helper = "Stop ignoring someone. /unignore user"

def __call__(self, serv, message):
for user in serv.active_users:
if not user:
return
newignore = serv.session.query(models.User).filter_by(name=message).first()
if not newignore:
serv.send_message("Unknown user %s" % with_color(message), to="me")
return
ignore = serv.session.query(models.Relationship).filter_by(user1_id = user.id).filter_by(user2_id = newignore.id).filter_by(state = 2).first()
if ignore:
serv.session.delete(ignore)
serv.session.commit()
serv.send_message("%s unignored" % with_color(message), to="me")
return
serv.send_message("%s is not currently ignored. Cant unignore" % with_color(message), to="me")



class Friendlist(ChatPlugin):
command = "friendlist"
helper = "Show friendlist"

def __call__(self, serv, message):
for user in serv.active_users:
if not user:
return
friends = serv.session.query(models.Relationship).filter_by(state = 1).filter((models.Relationship.user1_id == user.id) | models.Relationship.user2_id == user.id).all()
friendsStr = ""
for friend in friends:
if friend.user1_id == user.id:
frienduser = serv.session.query(models.User).filter_by(id = friend.user2_id).first()
else:
frienduser = serv.session.query(models.User).filter_by(id = friend.user1_id).first()
friendsStr += frienduser.name + ", "
if friendsStr.endswith(", "):
friendsStr = friendsStr[:-2]
requests = serv.session.query(models.Relationship).filter_by(user2_id = user.id).filter_by(state = 0).all()
requestsStr = ""
for request in requests:
requestsStr += serv.session.query(models.User).filter_by(id=request.user1_id).first().name + ", "
if requestsStr.endswith(", "):
requestsStr = requestsStr[:-2]
requestsoutgoing = serv.session.query(models.Relationship).filter_by(user1_id = user.id).filter_by(state = 0).all()
requestsoutgoingStr = ""
for request in requestsoutgoing:
requestsoutgoingStr += serv.session.query(models.User).filter_by(id=request.user2_id).first().name + ", "
if requestsoutgoingStr.endswith(", "):
requestsoutgoingStr = requestsoutgoingStr[:-2]
ignores = serv.session.query(models.Relationship).filter_by(user1_id = user.id).filter_by(state = 2).all()
ignoresStr = ""
for ignore in ignores:
ignoresStr += serv.session.query(models.User).filter_by(id=ignore.user2_id).first().name + ", "
if ignoresStr.endswith(", "):
ignoresStr = ignoresStr[:-2]

serv.send_message("Friends: %s" % friendsStr, to="me")
serv.send_message("Incoming requests: %s" % requestsStr, to="me")
serv.send_message("Outgoing requests: %s" % requestsoutgoingStr, to="me")
serv.send_message("Ignoring: %s" % ignoresStr, to="me")


class PrivateMessage(ChatPlugin):
command = "pm"
helper = "Send a private message. /pm user message"

def __call__(self, serv, message):
user = models.User.from_ids(serv.conn.users, serv.session)
user = user[0]
#user = serv.session.query(models.User).filter_by(online = True).filter_by(last_ip = serv.conn.ip).first()
if not user:
return
message = message.split(' ', 1)
if len(message) < 2:
serv.send_message("Need a text message to send", to="me")
return
if self.sendpm(serv, user, message[0], message[1]) == False:
if '_' in message[0]:
self.sendpm(serv, user, message[0].replace('_',' '), message[1])

def sendpm(self, serv, user, receptorname, message):
receptor = serv.session.query(models.User).filter_by(online=True).filter_by(name=receptorname).first()
if not receptor:
serv.send_message("Could not find %s online" % with_color(receptorname), to="me")
return False
if receptor.name == user.name:
serv.send_message("Cant pm yourself", to="me")
return False
ignore = serv.session.query(models.Relationship).filter( \
(((models.Relationship.user1_id == user.id) & (models.Relationship.user2_id == receptor.id)) | \
((models.Relationship.user2_id == user.id) & (models.Relationship.user1_id == receptor.id))) & \
(models.Relationship.state == 2)).first()
if ignore:
serv.send_message("Cant send %s a private message" %with_color(receptorname), to="me")
return False
if not receptor:
serv.send_message("Could not find %s online" % with_color(receptorname), to="me")
return False
serv.send_message("To %s : %s" % (with_color(receptor.name), message), to="me")
receptor = serv.server.find_connection(receptor.id)
#if i do what's commented both players get the message
#serv.send_message("From %s : %s" % (with_color(user.name), message), receptor)
receptor.send(smutils.smpacket.SMPacketServerNSCCM(message="From %s : %s" % (with_color(user.name), message)))
return True

19 changes: 19 additions & 0 deletions smserver/controllers/legacy/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ def handle(self):
))

self.send(models.Room.smo_list(self.session, self.active_users))
friends = self.session.query(models.Relationship).filter_by(state = 1).filter((models.Relationship.user1_id == user.id) | (models.Relationship.user2_id == user.id)).all()
for friend in friends:
if friend.user1_id == user.id:
friendid = friend.user2_id
else:
friendid = friend.user1_id
friendconn = self.server.find_connection(friendid)
self.server.send_friend_list(friendid, friendconn)
frienduser = self.session.query(models.User).filter_by(id = friendid).first()
if frienduser.online == True:
if frienduser.friend_notifications == True and friendconn:
self.send_message(
"Your friend %s connected" % user.name,
friendconn)
if user.friend_notifications:
self.send_message(
"Your friend %s is online" % frienduser.name,
to="me")
self.server.send_friend_list(user.id, self.conn)

def _send_server_resume(self, nb_onlines, max_users):
self.send_message(self.server.config.server.get("motd", ""), to="me")
Expand Down
1 change: 1 addition & 0 deletions smserver/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
from smserver.models.ban import Ban
from smserver.models.game import Game
from smserver.models.connection import Connection
from smserver.models.relationship import Relationship
32 changes: 32 additions & 0 deletions smserver/models/relationship.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python3
# -*- coding: utf8 -*-


import datetime
import enum
from sqlalchemy import Column, Integer, String, DateTime, Boolean, ForeignKey, func
from sqlalchemy.orm import relationship, reconstructor, object_session

from smserver.models import schema
from smserver.chathelper import with_color, nick_color
from smserver.models.privilege import Privilege
from smserver import ability

class Relationship(schema.Base):
__tablename__ = 'relationships'

REPR = {
0: "",
2: "%",
3: "@",
5: "&",
10: "~"
}

id = Column(Integer, primary_key=True)
user1_id = Column(Integer)
user2_id = Column(Integer)
state = Column(Integer, default=0)

def __repr__(self):
return "<Relationship #%s (user1_id='%s', user2_id='%s')>" % (self.id, self.user1_id, self.user2_id)
2 changes: 2 additions & 0 deletions smserver/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class User(schema.Base):
status = Column(Integer, default=1)
chat_timestamp = Column(Boolean, default=False)

friend_notifications = Column(Boolean, default=False)

room_id = Column(Integer, ForeignKey('rooms.id'))
room = relationship("Room", back_populates="users")

Expand Down
51 changes: 50 additions & 1 deletion smserver/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,22 @@ def on_disconnect(self, session, conn): #pylint: disable=arguments-differ
for user in users:
models.User.disconnect(user, session)
self.log.info("Player %s disconnected", user.name)


friends = session.query(models.Relationship).filter_by(state = 1).filter((models.Relationship.user1_id == user.id) | (models.Relationship.user2_id == user.id)).all()
for friend in friends:
if friend.user1_id == user.id:
friendid = friend.user2_id
else:
friendid = friend.user1_id
friendconn = self.find_connection(friendid)
self.send_friend_list(friendid, friendconn)
frienduser = session.query(models.User).filter_by(id = friendid).first()
if frienduser.online == True and frienduser.friend_notifications == True and not friendconn == None:
self.send_message(
"Your friend %s disconnected" % user.name,
conn=friendconn
)

room = connection.room
if room:
self.send_message(
Expand All @@ -272,6 +287,40 @@ def send_user_list(self, room):

self.sendroom(room.id, room.nsccuul)


def send_friend_list(self, userid, conn):

return

"""
Requires FLU packets added in smpacket
def send_friend_list(self, userid, conn):
if conn == None:
return
usernames = []
userstates = []
with self.db.session_scope() as session:
friends = session.query(models.Relationship).filter_by(state = 1).filter((models.Relationship.user1_id == userid) | (models.Relationship.user2_id == userid)).all()

for friend in friends:
if friend.user1_id == userid:
frienduser = session.query(models.User).filter_by(id = friend.user2_id).first()
else:
frienduser = session.query(models.User).filter_by(id = friend.user1_id).first()
usernames.append(frienduser.name)
if frienduser.online == True:
userstates.append(1 + frienduser.status)
else:
userstates.append(0)


packet = smpacket.SMPacketServerFLU(
nb_players=len(usernames),
players=[{"name": name, "status": state}
for name, state in zip(usernames, userstates)]
)
conn.send(packet)
"""
def send_message(self, message, room=None, conn=None, func=None):
"""
Send a chat message (default to all)
Expand Down