File size: 5,469 Bytes
0aee47a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""

bilibili_api.utils.Danmaku



弹幕类。

"""

import time
from enum import Enum
from typing import Union

from .utils import crack_uid as _crack_uid


class DmFontSize(Enum):
    """

    字体大小枚举。

    """

    EXTREME_SMALL = 12
    SUPER_SMALL = 16
    SMALL = 18
    NORMAL = 25
    BIG = 36
    SUPER_BIG = 45
    EXTREME_BIG = 64


class DmMode(Enum):
    """

    弹幕模式枚举。

    """

    FLY = 1
    TOP = 5
    BOTTOM = 4
    REVERSE = 6
    SPECIAL = 9


class Danmaku:
    """

    弹幕类。

    """

    def __init__(

        self,

        text: str,

        dm_time: float = 0.0,

        send_time: float = time.time(),

        crc32_id: str = "",

        color: str = "ffffff",

        weight: int = -1,

        id_: int = -1,

        id_str: str = "",

        action: str = "",

        mode: Union[DmMode, int] = DmMode.FLY,

        font_size: Union[DmFontSize, int] = DmFontSize.NORMAL,

        is_sub: bool = False,

        pool: int = 0,

        attr: int = -1,

        uid: int = -1,

    ):
        """

        Args:

            (self.)text      (str)                             : 弹幕文本。



            (self.)dm_time   (float, optional)                 : 弹幕在视频中的位置,单位为秒。Defaults to 0.0.



            (self.)send_time (float, optional)                 : 弹幕发送的时间。Defaults to time.time().



            (self.)crc32_id  (str, optional)                   : 弹幕发送者 UID 经 CRC32 算法取摘要后的值。Defaults to "".



            (self.)color     (str, optional)                   : 弹幕十六进制颜色。Defaults to "ffffff" (如果为大会员专属的颜色则为"special").



            (self.)weight    (int, optional)                   : 弹幕在弹幕列表显示的权重。Defaults to -1.



            (self.)id_       (int, optional)                   : 弹幕 ID。Defaults to -1.



            (self.)id_str    (str, optional)                   : 弹幕字符串 ID。Defaults to "".



            (self.)action    (str, optional)                   : 暂不清楚。Defaults to "".



            (self.)mode      (Union[DmMode, int], optional)    : 弹幕模式。Defaults to Mode.FLY.



            (self.)font_size (Union[DmFontSize, int], optional): 弹幕字体大小。Defaults to FontSize.NORMAL.



            (self.)is_sub    (bool, optional)                  : 是否为字幕弹幕。Defaults to False.



            (self.)pool      (int, optional)                   : 池。Defaults to 0.



            (self.)attr      (int, optional)                   : 暂不清楚。 Defaults to -1.



            (self.)uid       (int, optional)                   : 弹幕发送者 UID。Defaults to -1.



        大会员专属颜色文字填充:http://i0.hdslb.com/bfs/dm/9dcd329e617035b45d2041ac889c49cb5edd3e44.png



        大会员专属颜色背景填充:http://i0.hdslb.com/bfs/dm/ba8e32ae03a0a3f70f4e51975a965a9ddce39d50.png

        """
        self.text = text
        self.dm_time = dm_time
        self.send_time = send_time
        self.crc32_id = crc32_id
        self.color = color
        self.weight = weight
        self.id_ = id_
        self.id_str = id_str
        self.action = action
        self.mode = mode.value if isinstance(mode, DmMode) else mode
        self.font_size = (
            font_size.value if isinstance(font_size, DmFontSize) else font_size
        )
        self.is_sub = is_sub
        self.pool = pool
        self.attr = attr
        self.uid = uid

    def __str__(self):
        ret = "%s, %s, %s" % (self.send_time, self.dm_time, self.text)
        return ret

    def __len__(self):
        return len(self.text)

    @staticmethod
    def crack_uid(crc32_id: str):
        """

        (@staticmethod)



        暴力破解 UID,可能存在误差,请慎重使用。



        精确至 UID 小于 10000000 的破解。



        Args:

            crc32_id (str): crc32 id



        Returns:

            int: 真实 UID。

        """
        return int(_crack_uid(crc32_id))

    def to_xml(self):
        """

        将弹幕转换为 xml 格式弹幕

        """
        txt = self.text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
        string = f'<d p="{self.dm_time},{self.mode},{self.font_size},{int(self.color, 16)},{self.send_time},{self.pool},{self.crc32_id},{self.id_},11">{txt}</d>'
        return string


class SpecialDanmaku:
    def __init__(

        self,

        content: str,

        id_: int = -1,

        id_str: str = "",

        mode: Union[DmMode, int] = DmMode.SPECIAL,

        pool: int = 2,

    ):
        """

        Args:

            (self.)content (str)               : 弹幕内容



            (self.)id_     (int)               : 弹幕 id. Defaults to -1.



            (self.)id_str  (str)               : 弹幕 id (string 类型). Defaults to "".



            (self.)mode    (Union[DmMode, int]): 弹幕类型. Defaults to DmMode.SPECIAL.



            (self.)pool    (int)               : 弹幕池. Defaults to 2.

        """
        self.content = content
        self.id_ = id_
        self.id_str = id_str
        self.mode = mode.value if isinstance(mode, DmMode) else mode
        self.pool = pool

    def __str__(self):
        return f"{self.content}"