summaryrefslogtreecommitdiff
path: root/tidal_dl_ng/config.py
blob: bdcc70db6364119f6f6ca0255facfac0fb89c616 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from typing import Any

from collections.abc import Callable
from json import JSONDecodeError

import tidalapi
from tidal_dl_ng.helper.decorator import SingletonMeta
from tidal_dl_ng.helper.path import path_file_settings, path_file_token
from tidal_dl_ng.model.cfg import Settings as ModelSettings
from tidal_dl_ng.model.cfg import Token as ModelToken
from requests import HTTPError


class BaseConfig:
    data: ModelSettings | ModelToken = None
    file_path: str = None
    cls_model: object = None

    def save(self) -> None:
        data_json = self.data.to_json()

        with open(self.file_path, encoding="utf-8", mode="w") as f:
            f.write(data_json)

    def set_option(self, key: str, value: Any) -> None:
        setattr(self.data, key, value)

    def read(self, path: str) -> bool:
        result = False

        try:
            with open(path, encoding="utf-8") as f:
                settings_json = f.read()

            self.data = self.cls_model.from_json(settings_json)
            result = True
        except (JSONDecodeError, TypeError, FileNotFoundError):
            self.data = self.cls_model()
            self.save()

        return result


class Settings(BaseConfig, metaclass=SingletonMeta):
    cls_model = ModelSettings
    data = None

    def __init__(self):
        self.file_path = path_file_settings()
        self.read(self.file_path)


class Tidal(BaseConfig, metaclass=SingletonMeta):
    cls_model = ModelToken
    session: tidalapi.Session = None
    data: ModelToken = None
    token_from_storage: bool = False
    settings: Settings = None

    def __init__(self, settings: Settings = None):
        self.session = tidalapi.Session()
        self.session.video_quality = tidalapi.VideoQuality.high
        self.file_path = path_file_token()
        self.token_from_storage = self.read(self.file_path)
        self.login_token()

        if settings:
            self.settings = settings
            self.settings_apply()

    def settings_apply(self, settings: Settings = None) -> bool:
        if settings:
            self.settings = settings

        self.session.audio_quality = self.settings.data.quality_audio

        return True

    def login_token(self) -> bool:
        result = False

        if self.token_from_storage:
            try:
                result = self.session.load_oauth_session(
                    self.data.token_type, self.data.access_token, self.data.refresh_token, self.data.expiry_time
                )
            except HTTPError:
                result = False

        return result

    def login_oauth_start(self, function=print) -> None:
        self.session.login_oauth_simple(function)

    def login_oauth_finish(self) -> bool:
        result = self.session.check_login()

        if result:
            self.token_persist()

        return result

    def token_persist(self) -> None:
        self.set_option("token_type", self.session.token_type)
        self.set_option("access_token", self.session.access_token)
        self.set_option("refresh_token", self.session.refresh_token)
        self.set_option("expiry_time", self.session.expiry_time)
        self.save()

    def login(self, fn_print: Callable) -> bool:
        is_token = self.login_token()
        result = False

        if is_token:
            fn_print("Yep, looks good! You are logged in.")

            result = True
        elif not is_token:
            fn_print("You either do not have a token or your token is invalid.")
            fn_print("No worries, we will handle this...")
            self.login_oauth_start(fn_print)

            is_login = self.login_oauth_finish()

            if is_login:
                fn_print("The login was successful. I have stored your credentials (token).")

                result = True
            else:
                fn_print("Something went wrong. Did you login using your browser correctly? May try again...")

        return result