bot.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #!/usr/bin/env python3
  2. import requests
  3. import asyncio
  4. import websockets
  5. import logging
  6. import time
  7. from random import randint
  8. import messages_pb2
  9. logging.basicConfig(level=logging.INFO)
  10. # Test
  11. #PUSHER = "world-test.fixme.ch"
  12. #ROOM = "_%2Fglobal%2Fworld-test.fixme.ch%2Fmaps%2Ffixme.json"
  13. # Prod
  14. PUSHER = "pusher.world.fixme.ch"
  15. ROOM = "_%2Fglobal%2Fmaps.world.fixme.ch%2Ffixme%2Ffixme.json"
  16. # Bot info
  17. name = "FIXMYBOT"
  18. character = "Female4"
  19. character = ["color_28","eyes_23","hair_1","clothes_50","hats_1","accessory_23"]
  20. bot_x = 382
  21. bot_y = 305
  22. bot_current_x = bot_x
  23. bot_current_y = bot_y
  24. bot_viewport = 0, 0, 640, 360
  25. bot_idle = True
  26. bot_task = None
  27. # Get session
  28. s = requests.Session()
  29. r = s.post("https://{}/anonymLogin".format(PUSHER))
  30. authToken = r.json()["authToken"]
  31. userUuid = r.json()["userUuid"]
  32. logging.debug("authToken: {}".format(authToken))
  33. logging.debug("userUuid: {}".format(userUuid))
  34. # Create URI
  35. uri = "wss://{}/room?roomId={}&token={}&name={}&{}&x={}&y={}&top={}&left={}&right={}&bottom={}".format(
  36. PUSHER, ROOM, authToken, name,
  37. 'characterLayers='+'&characterLayers='.join(character),
  38. bot_x, bot_y, bot_viewport[0], bot_viewport[1], bot_viewport[2], bot_viewport[3],)
  39. def lerp(a, b, t):
  40. return int(a + (b-a) * t)
  41. async def Move(ws, position, prox=50, far=120, speed=10, steps=11):
  42. global bot_current_x, bot_current_y, bot_idle
  43. bot_idle = False
  44. # Don't move if too far or too close
  45. abs_pos_x = abs(position.x - bot_current_x)
  46. abs_pos_y = abs(position.y - bot_current_y)
  47. if abs_pos_x < prox + 10 and abs_pos_y < prox + 10:
  48. return
  49. if abs_pos_x > far and abs_pos_y < far:
  50. return
  51. # Don't move too close to player
  52. dest_x = position.x - prox if (position.x - bot_current_x > 0) else position.x + prox
  53. dest_y = position.y - prox if (position.y - bot_current_y > 0) else position.y + prox
  54. # Moving steps
  55. for i in range(steps):
  56. t = i / speed
  57. bot_current_x = lerp(bot_current_x, dest_x, t)
  58. bot_current_y = lerp(bot_current_y, dest_y, t)
  59. message = messages_pb2.ClientToServerMessage(
  60. userMovesMessage=messages_pb2.UserMovesMessage(
  61. position = messages_pb2.PositionMessage(x=bot_current_x, y=bot_current_y, direction=position.direction, moving=True,),
  62. viewport = messages_pb2.ViewportMessage(left=bot_viewport[0], top=bot_viewport[1], right=bot_viewport[2], bottom=bot_viewport[3]),
  63. ),
  64. )
  65. await ws.send(message.SerializeToString())
  66. time.sleep(0.05)
  67. # Stop moving at last position
  68. message = messages_pb2.ClientToServerMessage(
  69. userMovesMessage=messages_pb2.UserMovesMessage(
  70. position = messages_pb2.PositionMessage(x=bot_current_x, y=bot_current_y, direction='DOWN', moving=False,),
  71. viewport = messages_pb2.ViewportMessage(left=bot_viewport[0], top=bot_viewport[1], right=bot_viewport[2], bottom=bot_viewport[3]),
  72. ),
  73. )
  74. await ws.send(message.SerializeToString())
  75. bot_idle = True
  76. async def SendGlobalMessage(ws, name):
  77. message = messages_pb2.ClientToServerMessage(
  78. playGlobalMessage=messages_pb2.PlayGlobalMessage(
  79. id='1', type='message', message='Hello {}, <br/><br/> Welcome to VirtualFIXME !'.format(name)
  80. ),
  81. #stopGlobalMessage=messages_pb2.StopGlobalMessage(id='1')
  82. )
  83. await ws.send(message.SerializeToString())
  84. logging.info("message sent: {}".format(message.SerializeToString()))
  85. def getMessages(message):
  86. if message.WhichOneof("message") == "batchMessage":
  87. for msg in message.batchMessage.payload:
  88. yield msg
  89. else:
  90. return [message]
  91. async def bot_move():
  92. global bot_task
  93. async with websockets.connect(uri) as websocket:
  94. while True:
  95. print('bot_idle={}'.format(bot_idle))
  96. print('bot_task={}'.format(bot_task))
  97. if bot_idle and (not bot_task or bot_task.done()):
  98. rand_x = randint(bot_viewport[0], bot_viewport[2])
  99. rand_y = randint(bot_viewport[1], bot_viewport[3])
  100. position = messages_pb2.PositionMessage(x=rand_x, y=rand_y, direction='DOWN')
  101. bot_task = asyncio.create_task(Move(websocket, position, prox=25, steps=100))
  102. await asyncio.sleep(1)
  103. async def bot():
  104. global bot_task
  105. async with websockets.connect(uri) as websocket:
  106. while True:
  107. data = await websocket.recv()
  108. message = messages_pb2.ServerToClientMessage()
  109. message.ParseFromString(data)
  110. for msg in getMessages(message):
  111. #print(msg)
  112. if msg.WhichOneof("message") == "userMovedMessage": # and msg.userMovedMessage.position.moving != True:
  113. if bot_task != None:
  114. bot_task.cancel()
  115. bot_task = asyncio.create_task(Move(websocket, msg.userMovedMessage.position))
  116. if msg.WhichOneof("message") == "userLeftMessage":
  117. #if bot_task != None:
  118. # bot_task.cancel()
  119. #position = messages_pb2.PositionMessage(x=bot_x, y=bot_y, direction='DOWN')
  120. #bot_task = asyncio.create_task(Move(websocket, position, prox=0))
  121. pass
  122. if msg.WhichOneof("message") == "userJoinedMessage":
  123. # Send message to mattermost !
  124. #await SendGlobalMessage(websocket, msg.userJoinedMessage.name)
  125. pass
  126. #TODO: shared handler to have multiple tasks using the websocket
  127. asyncio.get_event_loop().run_until_complete(
  128. asyncio.gather(
  129. bot(),
  130. #bot_move()
  131. )
  132. )