Passed
Push — main ( 5fd39b...ff01c0 )
by
unknown
01:35
created

heartbeat.get_heartbeat()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 9
rs 10
c 0
b 0
f 0
cc 1
nop 0
1
# -*- coding: utf-8 -*-
2
# MIT License
3
#
4
# Copyright (c) 2021 Pincer
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining a copy
7
# of this software and associated documentation files (the "Software"), to deal
8
# in the Software without restriction, including without limitation the rights
9
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
# copies of the Software, and to permit persons to whom the Software is
11
# furnished to do so, subject to the following conditions:
12
#
13
# The above copyright notice and this permission notice shall be included in all
14
# copies or substantial portions of the Software.
15
#
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
# SOFTWARE.
23
24
from __future__ import annotations
25
26
import logging
27
from asyncio import sleep
28
from typing import Optional
29
30
from websockets.legacy.client import WebSocketClientProtocol
31
32
from pincer import __package__
33
from pincer.core.dispatch import GatewayDispatch
34
from pincer.exceptions import HeartbeatError
35
36
heartbeat: float = 0
37
sequence: Optional[int] = None
38
39
log = logging.getLogger(__package__)
40
41
42
def get_heartbeat() -> float:
43
    """
44
    Get the current heartbeat.
45
46
    :return: The current heartbeat of the client.
47
            Default is 0 (client has not initialized the heartbeat yet.)
48
49
    """
50
    return heartbeat
51
52
53
async def __send_heartbeat(socket: WebSocketClientProtocol):
54
    # TODO: Fix docs
55
56
    global sequence
57
58
    log.debug(f"Sending heartbeat (seq: {sequence})")
59
    await socket.send(str(GatewayDispatch(1, sequence)))
60
61
62
async def handle_hello(socket: WebSocketClientProtocol,
63
                       payload: GatewayDispatch):
64
    # TODO: Fix docs
65
    global heartbeat
66
67
    log.debug("Handling initial discord hello websocket message.")
68
    heartbeat = payload.data.get("heartbeat_interval")
69
70
    if not heartbeat:
71
        log.error("No `heartbeat_interval` is present. Has the API changed? "
72
                  f"(payload: {payload})")
73
        raise HeartbeatError("Discord hello is missing `heartbeat_interval` "
74
                             "in payload. Because of this the client can not "
75
                             f"maintain a connection. Check logging for more "
76
                             f"information.")
77
78
    heartbeat /= 1000
79
    log.debug(f"Maintaining a connection with heartbeat: {heartbeat}")
80
81
    await __send_heartbeat(socket)
82
83
84
async def handle_heartbeat(socket: WebSocketClientProtocol, _):
85
    # TODO: Fix docs
86
    global heartbeat
87
88
    logging.debug(f"Resting heart for {heartbeat}s")
89
    await sleep(heartbeat)
90
    await __send_heartbeat(socket)
91