gs_query.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. """DWC Network Server Emulator
  2. Copyright (C) 2014 polaris-
  3. Copyright (C) 2014 ToadKing
  4. Copyright (C) 2014 AdmiralCurtiss
  5. Copyright (C) 2016 Sepalani
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Affero General Public License as
  8. published by the Free Software Foundation, either version 3 of the
  9. License, or (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU Affero General Public License for more details.
  14. You should have received a copy of the GNU Affero General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. """
  17. def parse_gamespy_message(message):
  18. """Parse a GameSpy message."""
  19. stack = []
  20. messages = {}
  21. msg = message
  22. while len(msg) > 0 and msg[0] == '\\' and "\\final\\" in msg:
  23. # Find the command
  24. # Don't search for more commands if there isn't a \final\, save the
  25. # left over for the next packet
  26. found_command = False
  27. while len(msg) > 0 and msg[0] == '\\':
  28. keyEnd = msg[1:].index('\\') + 1
  29. key = msg[1:keyEnd]
  30. msg = msg[keyEnd + 1:]
  31. if key == "final":
  32. break
  33. if '\\' in msg:
  34. if msg[0] == '\\':
  35. value = ""
  36. else:
  37. valueEnd = msg[1:].index('\\')
  38. value = msg[:valueEnd + 1]
  39. msg = msg[valueEnd + 1:]
  40. else:
  41. value = msg
  42. if not found_command:
  43. messages['__cmd__'] = key
  44. messages['__cmd_val__'] = value
  45. found_command = True
  46. messages[key] = value
  47. stack.append(messages)
  48. messages = {}
  49. # Return msg so we can prepend any leftover commands to the next packet.
  50. return stack, msg
  51. def create_gamespy_message_from_dict(messages):
  52. """Generate a list based on the input dictionary.
  53. The main command must also be stored in __cmd__ for it to put the
  54. parameter at the beginning.
  55. """
  56. cmd = messages.get("__cmd__", "")
  57. cmd_val = messages.get("__cmd_val__", "")
  58. l = [("__cmd__", cmd), ("__cmd_val__", cmd_val)]
  59. l.extend([
  60. (key, value)
  61. for key, value in messages.items()
  62. if key not in (cmd, "__cmd__", "__cmd_val__")
  63. ])
  64. return l
  65. def create_gamespy_message_from_list(messages):
  66. """Generate a string based on the input list."""
  67. cmd = ""
  68. cmd_val = ""
  69. query = ""
  70. for message in messages:
  71. if len(message) == 1:
  72. query += str(message[0])
  73. elif message[0] == "__cmd__":
  74. cmd = str(message[1]).strip('\\')
  75. elif message[0] == "__cmd_val__":
  76. cmd_val = str(message[1]).strip('\\')
  77. else:
  78. query += "\\%s\\%s" % (str(message[0]).strip('\\'),
  79. str(message[1]).strip('\\'))
  80. if cmd:
  81. # Prepend the main command if one was found.
  82. query = "\\%s\\%s%s" % (cmd, cmd_val, query)
  83. return query
  84. def create_gamespy_message(messages, id=None):
  85. """Create a message based on a dictionary (or list) of parameters."""
  86. if isinstance(messages, dict):
  87. messages = create_gamespy_message_from_dict(messages)
  88. # Check for an id if the id needs to be updated.
  89. if id is not None:
  90. for i, message in enumerate(messages):
  91. # If it already exists in the list then update it
  92. if message[0] == "id":
  93. messages[i] = ("id", str(id))
  94. break
  95. else:
  96. # Otherwise, add it in the list
  97. messages.append(("id", str(id)))
  98. query = create_gamespy_message_from_list(messages)
  99. query += "\\final\\"
  100. return query