OverloadedOrama

Making a Discord Bot with Godot (Part Two)

Jul 2nd, 2019
128
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. extends HTTPRequest
  2.  
  3. var token := "YourTokenHere" #make sure to actually replace this with your token!
  4. var client : WebSocketClient
  5. var heartbeat_interval : float
  6. var last_sequence : float
  7. var session_id : String
  8. var heartbeat_ack_received := true
  9. var invalid_session_is_resumable : bool
  10.  
  11. func _ready() -> void:
  12. randomize()
  13. client = WebSocketClient.new()
  14. client.connect_to_url("wss://gateway.discord.gg/?v=6&encoding=json")
  15. client.connect("connection_established", self, "_connection_established")
  16. client.connect("connection_closed", self, "_connection_closed")
  17. client.connect("server_close_request", self, "_server_close_request")
  18. client.connect("data_received", self, "_data_received")
  19.  
  20. func _process(delta : float) -> void:
  21. #check if the client is not disconnected, there's no point to poll it if it is
  22. if client.get_connection_status() != NetworkedMultiplayerPeer.CONNECTION_DISCONNECTED:
  23. client.poll()
  24. else:
  25. #If it is disconnected, try to resume
  26. client.connect_to_url("wss://gateway.discord.gg/?v=6&encoding=json")
  27.  
  28. func _connection_established(protocol : String) -> void:
  29. print("We are connected! Protocol: %s" % protocol)
  30.  
  31. func _connection_closed(was_clean_close : bool) -> void:
  32. print("We disconnected. Clean close: %s" % was_clean_close)
  33.  
  34. func _server_close_request(code : int, reason : String) -> void:
  35. print("The server requested a clean close. Code: %s, reason: %s" % [code, reason])
  36.  
  37. func _data_received() -> void:
  38. var packet := client.get_peer(1).get_packet()
  39. var data := packet.get_string_from_utf8()
  40. var json_parsed := JSON.parse(data)
  41. var dict : Dictionary = json_parsed.result
  42. var op = str(dict["op"]) #convert it to string for easier checking
  43. match op:
  44. "0": #Opcode 0 Dispatch (Events)
  45. handle_events(dict)
  46. "9": #Opcode 9 Invalid Session
  47. invalid_session_is_resumable = dict["d"]
  48. $InvalidSessionTimer.one_shot = true
  49. $InvalidSessionTimer.wait_time = rand_range(1, 5)
  50. $InvalidSessionTimer.start()
  51. "10": #Opcode 10 Hello
  52. #Set our timer
  53. heartbeat_interval = dict["d"]["heartbeat_interval"] / 1000
  54. $HeartbeatTimer.wait_time = heartbeat_interval
  55. $HeartbeatTimer.start()
  56.  
  57. var d := {}
  58. if !session_id:
  59. #Send Opcode 2 Identify to the Gateway
  60. d = {
  61. "op" : 2,
  62. "d" : { "token" : token, "properties" : {} }
  63. }
  64. else:
  65. #Send Opcode 6 Resume to the Gateway
  66. d = {
  67. "op" : 6,
  68. "d" : { "token" : token, "session_id" : session_id, "seq" : last_sequence}
  69. }
  70. send_dictionary_as_packet(d)
  71. "11": #Opcode 11 Heartbeat ACK
  72. heartbeat_ack_received = true
  73. print("We've received a Heartbeat ACK from the gateway.")
  74.  
  75.  
  76. func _on_HeartbeatTimer_timeout() -> void: #Send Opcode 1 Heartbeat payloads every heartbeat_interval
  77. if !heartbeat_ack_received:
  78. #We haven't received a Heartbeat ACK back, so we'll disconnect
  79. client.disconnect_from_host(1002)
  80. return
  81. var d := {"op" : 1, "d" : last_sequence}
  82. send_dictionary_as_packet(d)
  83. heartbeat_ack_received = false
  84. print("We've send a Heartbeat to the gateway.")
  85.  
  86. func send_dictionary_as_packet(d : Dictionary) -> void:
  87. var query = to_json(d)
  88. client.get_peer(1).put_packet(query.to_utf8())
  89.  
  90. func handle_events(dict : Dictionary) -> void:
  91. last_sequence = dict["s"]
  92. var event_name : String = dict["t"]
  93. print(event_name)
  94. match event_name:
  95. "READY":
  96. session_id = dict["d"]["session_id"]
  97.  
  98. func _on_InvalidSessionTimer_timeout() -> void:
  99. var d := {}
  100. if invalid_session_is_resumable && session_id:
  101. #Send Opcode 6 Resume to the Gateway
  102. d = {
  103. "op" : 6,
  104. "d" : { "token" : token, "session_id" : session_id, "seq" : last_sequence}
  105. }
  106. else:
  107. #Send Opcode 2 Identify to the Gateway
  108. d = {
  109. "op" : 2,
  110. "d" : { "token" : token, "properties" : {} }
  111. }
  112. send_dictionary_as_packet(d)
RAW Paste Data