Passed
Push — master ( 2adcb6...75d235 )
by Markus
01:50
created

tcllib.requests.downloadrequest.get_vk2()   A

Complexity

Conditions 3

Size

Total Lines 14
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 3
nop 2
1
# -*- coding: utf-8 -*-
0 ignored issues
show
Coding Style introduced by
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
3
import binascii
4
import hashlib
5
import random
6
import time
7
import zlib
8
from collections import OrderedDict
9
from math import floor
10
from .. import devices
11
from .tclrequest import TclRequest
12
from .tclresult import DownloadResult
13
14
15
VDKEY_B64Z = b"eJwdjwEOwDAIAr8kKFr//7HhmqXp8AIIDrYAgg8byiUXrwRJRXja+d6iNxu0AhUooDCN9rd6rDLxmGIakUVWo3IGCTRWqCAt6X4jGEIUAxgN0eYWnp+LkpHQAg/PsO90ELsy0Npm/n2HbtPndFgGEV31R9OmT4O4nrddjc3Qt6nWscx7e+WRHq5UnOudtjw5skuV09pFhvmqnOEIs4ljPeel1wfLYUF4\n"
16
17
18
def get_salt():
19
    """Generate cryptographic salt."""
20
    millis = floor(time.time() * 1000)
21
    tail = "{:06d}".format(random.randint(0, 999999))
22
    return "{}{}".format(str(millis), tail)
23
24
def get_vk2(params_dict, cltp):
25
    """Generate salted hash of API parameters."""
26
    params_dict["cltp"] = cltp
27
    query = ""
28
    for key, val in params_dict.items():
29
        if query:
30
            query += "&"
31
        query += key + "=" + str(val)
32
    vdk = zlib.decompress(binascii.a2b_base64(VDKEY_B64Z))
33
    query += vdk.decode("utf-8")
34
    engine = hashlib.sha1()
35
    engine.update(bytes(query, "utf-8"))
36
    hexhash = engine.hexdigest()
37
    return hexhash
38
39
class DownloadRequest(TclRequest):
0 ignored issues
show
Coding Style introduced by
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
best-practice introduced by
Too many instance attributes (9/7)
Loading history...
Unused Code introduced by
The variable __class__ seems to be unused.
Loading history...
40
    def __init__(self, device: devices.Device, tvver: str, fw_id: str):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable devices does not seem to be defined.
Loading history...
41
        super().__init__()
42
        self.uri = "/download_request.php"
43
        self.method = "POST"
44
        self.device = device
45
        self.tvver = tvver
46
        self.fw_id = fw_id
47
48
    def get_headers(self):
49
        return {"User-Agent": self.device.ua}
50
51
    def get_params(self):
52
        params = OrderedDict()
53
        params["id"] = self.device.imei
54
        params["salt"] = get_salt()
55
        params["curef"] = self.device.curef
56
        params["fv"] = self.device.fwver
57
        params["tv"] = self.tvver
58
        params["type"] = self.device.type
59
        params["fw_id"] = self.fw_id
60
        params["mode"] = self.device.mode
61
        params["vk"] = get_vk2(params, self.device.cltp)
62
        params["cltp"] = self.device.cltp
63
        params["cktp"] = self.device.cktp
64
        params["rtd"] = self.device.rtd
65
        if self.device.mode == self.device.MODE_STATES["FULL"]:
66
            params["foot"] = 1
67
        params["chnl"] = self.device.chnl
68
        return params
69
70
    def is_done(self, http_status: int, contents: str) -> bool:
71
        if http_status == 200:
72
            self.response = contents
73
            self.result = DownloadResult(contents)
74
            self.success = True
75
            return True
76
        elif http_status not in [500, 502, 503]:
77
            # Errors OTHER than 500, 502 or 503 are probably
78
            # errors where we don't need to retry
79
            self.error = "HTTP {}".format(http_status)
80
            self.success = False
81
            return True
82
        return False
83