Passed
Push — master ( 818b9b...d8a06d )
by
unknown
02:07
created

ck_bilibili.BiliBili.report_task()   A

Complexity

Conditions 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nop 5
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2
"""
3
cron: 30 8 * * *
4
new Env('Bilibili');
5
"""
6
import time
7
8
import requests
9
10
from notify_mtr import send
11
from utils import get_data
12
13
14
class BiliBili(object):
15
    def __init__(self, check_items):
16
        self.check_items = check_items
17
18
    @staticmethod
19
    def get_nav(session):
20
        url = "https://api.bilibili.com/x/web-interface/nav"
21
        res = session.get(url=url).json()
22
        uname = res.get("data", {}).get("uname")
23
        uid = res.get("data", {}).get("mid")
24
        is_login = res.get("data", {}).get("isLogin")
25
        coin = res.get("data", {}).get("money")
26
        vip_type = res.get("data", {}).get("vipType")
27
        current_exp = res.get("data", {}).get("level_info", {}).get("current_exp")
28
        return uname, uid, is_login, coin, vip_type, current_exp
29
30
    @staticmethod
31
    def reward(session) -> list:
32
        """取B站经验信息"""
33
        url = "https://api.bilibili.com/x/member/web/exp/log?jsonp=jsonp"
34
        today = time.strftime('%Y-%m-%d', time.localtime())
35
        return list(
36
            filter(lambda x: x['time'].split()[0] == today, session.get(url=url).json().get("data").get("list")))
37
38
    @staticmethod
39
    def live_sign(session) -> str:
40
        """B站直播签到"""
41
        try:
42
            url = "https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign"
43
            res = session.get(url=url).json()
44
            if res["code"] == 0:
45
                msg = f'签到成功,{res["data"]["text"]},特别信息:{res["data"]["specialText"]},本月已签到{res["data"]["hadSignDays"]}天'
46
            elif res["code"] == 1011040:
47
                msg = "今日已签到过,无法重复签到"
48
            else:
49
                msg = f'签到失败,信息为: {res["message"]}'
50
        except Exception as e:
51
            msg = f"签到异常,原因为{str(e)}"
52
            print(msg)
53
        return msg
54
55
    @staticmethod
56
    def manga_sign(session, platform="android") -> str:
57
        """
58
        模拟B站漫画客户端签到
59
        """
60
        try:
61
            url = "https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn"
62
            post_data = {"platform": platform}
63
            res = session.post(url=url, data=post_data).json()
64
            if res["code"] == 0:
65
                msg = "签到成功"
66
            elif res["msg"] == "clockin clockin is duplicate":
67
                msg = "今天已经签到过了"
68
            else:
69
                msg = f'签到失败,信息为({res["msg"]})'
70
                print(msg)
71
        except Exception as e:
72
            msg = f"签到异常,原因为: {str(e)}"
73
            print(msg)
74
        return msg
75
76
    @staticmethod
77
    def vip_privilege_receive(session, bili_jct, receive_type: int = 1) -> dict:
78
        """
79
        领取B站大会员权益
80
        receive_type int 权益类型,1为B币劵,2为优惠券
81
        """
82
        url = "https://api.bilibili.com/x/vip/privilege/receive"
83
        post_data = {"type": receive_type, "csrf": bili_jct}
84
        res = session.post(url=url, data=post_data).json()
85
        return res
86
87
    @staticmethod
88
    def vip_manga_reward(session) -> dict:
89
        """获取漫画大会员福利"""
90
        url = "https://manga.bilibili.com/twirp/user.v1.User/GetVipReward"
91
        res = session.post(url=url, json={"reason_id": 1}).json()
92
        return res
93
94
    @staticmethod
95
    def report_task(session, bili_jct, aid: int, cid: int, progres: int = 300) -> dict:
96
        """
97
        B站上报视频观看进度
98
        aid int 视频av号
99
        cid int 视频cid号
100
        progres int 观看秒数
101
        """
102
        url = "http://api.bilibili.com/x/v2/history/report"
103
        post_data = {"aid": aid, "cid": cid, "progres": progres, "csrf": bili_jct}
104
        res = session.post(url=url, data=post_data).json()
105
        return res
106
107
    @staticmethod
108
    def share_task(session, bili_jct, aid) -> dict:
109
        """
110
        分享指定av号视频
111
        aid int 视频av号
112
        """
113
        url = "https://api.bilibili.com/x/web-interface/share/add"
114
        post_data = {"aid": aid, "csrf": bili_jct}
115
        res = session.post(url=url, data=post_data).json()
116
        return res
117
118
    @staticmethod
119
    def get_followings(
120
            session,
121
            uid: int,
122
            pn: int = 1,
123
            ps: int = 50,
124
            order: str = "desc",
125
            order_type: str = "attention",
126
    ) -> dict:
127
        """
128
        获取指定用户关注的up主
129
        uid int 账户uid,默认为本账户,非登录账户只能获取20个*5页
130
        pn int 页码,默认第一页
131
        ps int 每页数量,默认50
132
        order str 排序方式,默认desc
133
        order_type 排序类型,默认attention
134
        """
135
        params = {
136
            "vmid": uid,
137
            "pn": pn,
138
            "ps": ps,
139
            "order": order,
140
            "order_type": order_type,
141
        }
142
        url = "https://api.bilibili.com/x/relation/followings"
143
        res = session.get(url=url, params=params).json()
144
        return res
145
146
    @staticmethod
147
    def space_arc_search(
148
            session,
149
            uid: int,
150
            pn: int = 1,
151
            ps: int = 100,
152
            tid: int = 0,
153
            order: str = "pubdate",
154
            keyword: str = "",
155
    ):
156
        """
157
        获取指定up主空间视频投稿信息
158
        uid int 账户uid,默认为本账户
159
        pn int 页码,默认第一页
160
        ps int 每页数量,默认50
161
        tid int 分区 默认为0(所有分区)
162
        order str 排序方式,默认pubdate
163
        keyword str 关键字,默认为空
164
        """
165
        params = {
166
            "mid": uid,
167
            "pn": pn,
168
            "ps": ps,
169
            "tid": tid,
170
            "order": order,
171
            "keyword": keyword,
172
        }
173
        url = "https://api.bilibili.com/x/space/arc/search"
174
        res = session.get(url=url, params=params).json()
175
        data_list = [
176
            {
177
                "aid": one.get("aid"),
178
                "cid": 0,
179
                "title": one.get("title"),
180
                "owner": one.get("author"),
181
            }
182
            for one in res.get("data", {}).get("list", {}).get("vlist", [])
183
        ]
184
        return data_list
185
186
    @staticmethod
187
    def elec_pay(session, bili_jct, uid: int, num: int = 50) -> dict:
188
        """
189
        用B币给up主充电
190
        uid int up主uid
191
        num int 充电电池数量
192
        """
193
        url = "https://api.bilibili.com/x/ugcpay/trade/elec/pay/quick"
194
        post_data = {
195
            "elec_num": num,
196
            "up_mid": uid,
197
            "otype": "up",
198
            "oid": uid,
199
            "csrf": bili_jct,
200
        }
201
        res = session.post(url=url, data=post_data).json()
202
        return res
203
204
    @staticmethod
205
    def coin_add(
206
            session, bili_jct, aid: int, num: int = 1, select_like: int = 1
207
    ) -> dict:
208
        """
209
        给指定 av 号视频投币
210
        aid int 视频av号
211
        num int 投币数量
212
        select_like int 是否点赞
213
        """
214
        url = "https://api.bilibili.com/x/web-interface/coin/add"
215
        post_data = {
216
            "aid": aid,
217
            "multiply": num,
218
            "select_like": select_like,
219
            "cross_domain": "true",
220
            "csrf": bili_jct,
221
        }
222
        res = session.post(url=url, data=post_data).json()
223
224
        return res
225
226
    @staticmethod
227
    def live_status(session) -> str:
228
        """B站直播获取金银瓜子状态"""
229
        url = "https://api.live.bilibili.com/pay/v1/Exchange/getStatus"
230
        res = session.get(url=url).json()
231
        data = res.get("data")
232
        silver = data.get("silver", 0)
233
        gold = data.get("gold", 0)
234
        coin = data.get("coin", 0)
235
        msg = f"银瓜子数量: {silver}\n金瓜子数量: {gold}\n硬币数量: {coin}"
236
        return msg
237
238
    @staticmethod
239
    def silver2coin(session, bili_jct) -> dict:
240
        """银瓜子兑换硬币"""
241
        url = "https://api.live.bilibili.com/pay/v1/Exchange/silver2coin"
242
        post_data = {"csrf_token": bili_jct, "csrf": bili_jct}
243
        res = session.post(url=url, data=post_data).json()
244
        return res
245
246
    @staticmethod
247
    def get_region(session, rid=1, num=6):
248
        """
249
        获取 B站分区视频信息
250
        rid int 分区号
251
        num int 获取视频数量
252
        """
253
        url = (
254
                "https://api.bilibili.com/x/web-interface/dynamic/region?ps="
255
                + str(num)
256
                + "&rid="
257
                + str(rid)
258
        )
259
        res = session.get(url=url).json()
260
        data_list = [
261
            {
262
                "aid": one.get("aid"),
263
                "cid": one.get("cid"),
264
                "title": one.get("title"),
265
                "owner": one.get("owner", {}).get("name"),
266
            }
267
            for one in res.get("data", {}).get("archives", [])
268
        ]
269
        return data_list
270
271
    def main(self):
272
        msg_all = ""
273
        for check_item in self.check_items:
274
            cookie = {
275
                item.split("=")[0]: item.split("=")[1]
276
                for item in check_item.get("cookie").split("; ")
277
            }
278
            bili_jct = cookie.get("bili_jct")
279
            coin_num = check_item.get("coin_num", 0)
280
            coin_type = check_item.get("coin_type", 1)
281
            silver2coin = check_item.get("silver2coin", True)
282
            session = requests.session()
283
            requests.utils.add_dict_to_cookiejar(session.cookies, cookie)
284
            session.headers.update(
285
                {
286
                    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \
287
                     Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64",
288
                    "Referer": "https://www.bilibili.com/",
289
                    "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
290
                    "Connection": "keep-alive",
291
                }
292
            )
293
            success_count = 0
294
            uname, uid, is_login, coin, vip_type, current_exp = self.get_nav(
295
                session=session
296
            )
297
            if is_login:
298
                manhua_msg = self.manga_sign(session=session)
299
                live_msg = self.live_sign(session=session)
300
                aid_list = self.get_region(session=session)
301
                coins_av_count = len(list(filter(lambda x: x['reason'] == "视频投币奖励", self.reward(session=session))))
302
                coin_num = coin_num - coins_av_count
303
                coin_num = coin_num if coin_num < coin else coin
304
                if coin_type == 1 and coin_num:
305
                    following_list = self.get_followings(session=session, uid=uid)
306
                    for following in following_list.get("data", {}).get("list"):
307
                        mid = following.get("mid")
308
                        if mid:
309
                            aid_list += self.space_arc_search(session=session, uid=mid)
310
                if coin_num > 0:
311
                    for aid in aid_list[::-1]:
312
                        res = self.coin_add(
313
                            session=session, aid=aid.get("aid"), bili_jct=bili_jct
314
                        )
315
                        if res["code"] == 0:
316
                            coin_num -= 1
317
                            print(f'成功给{aid.get("title")}投一个币')
318
                            success_count += 1
319
                        elif res["code"] == 34005:
320
                            print(f'投币{aid.get("title")}失败,原因为{res["message"]}')
321
                            continue
322
                            # -104 硬币不够了 -111 csrf 失败 34005 投币达到上限
323
                        else:
324
                            print(f'投币{aid.get("title")}失败,原因为{res["message"]},跳过投币')
325
                            break
326
                        if coin_num <= 0:
327
                            break
328
                    coin_msg = f"今日成功投币{success_count + coins_av_count}/{check_item.get('coin_num', 5)}个"
329
                else:
330
                    coin_msg = (
331
                        f"今日成功投币{coins_av_count}/{check_item.get('coin_num', 5)}个"
332
                    )
333
                aid = aid_list[0].get("aid")
334
                cid = aid_list[0].get("cid")
335
                title = aid_list[0].get("title")
336
                report_res = self.report_task(
337
                    session=session, bili_jct=bili_jct, aid=aid, cid=cid
338
                )
339
                if report_res.get("code") == 0:
340
                    report_msg = f"观看《{title}》300秒"
341
                else:
342
                    report_msg = "任务失败"
343
                    print(report_msg)
344
                share_res = self.share_task(session=session, bili_jct=bili_jct, aid=aid)
345
                if share_res.get("code") == 0:
346
                    share_msg = f"分享《{title}》成功"
347
                else:
348
                    share_msg = "分享失败"
349
                    print(share_msg)
350
                if silver2coin:
351
                    silver2coin_res = self.silver2coin(
352
                        session=session, bili_jct=bili_jct
353
                    )
354
                    if silver2coin_res["code"] == 0:
355
                        silver2coin_msg = "成功将银瓜子兑换为1个硬币"
356
                    else:
357
                        silver2coin_msg = silver2coin_res["message"]
358
                else:
359
                    silver2coin_msg = "未开启银瓜子兑换硬币功能"
360
                live_stats = self.live_status(session=session)
361
                (
362
                    uname,
363
                    uid,
364
                    is_login,
365
                    new_coin,
366
                    vip_type,
367
                    new_current_exp,
368
                ) = self.get_nav(session=session)
369
                # reward_res = self.reward(session=session)
370
                # login = reward_res.get("data", {}).get("login")
371
                # watch_av = reward_res.get("data", {}).get("watch_av")
372
                # coins_av = reward_res.get("data", {}).get("coins_av", 0)
373
                # share_av = reward_res.get("data", {}).get("share_av")
374
                # today_exp = 5 * len([one for one in [login, watch_av, share_av] if one])
375
                # today_exp += coins_av
376
                today_exp = sum(map(lambda x: x['delta'], self.reward(session=session)))
377
                update_data = (28800 - new_current_exp) // (
378
                    today_exp if today_exp else 1
379
                )
380
                msg = (
381
                    f"帐号信息: {uname}\n漫画签到: {manhua_msg}\n直播签到: {live_msg}\n"
382
                    f"登陆任务: 今日已登陆\n观看视频: {report_msg}\n分享任务: {share_msg}\n投币任务: {coin_msg}\n"
383
                    f"银瓜子兑换硬币: {silver2coin_msg}\n今日获得经验: {today_exp}\n当前经验: {new_current_exp}\n"
384
                    f"按当前速度升级还需: {update_data}天\n{live_stats}"
385
                )
386
                msg_all += msg + "\n\n"
387
        return msg_all
388
389
390
if __name__ == "__main__":
391
    data = get_data()
392
    _check_items = data.get("BILIBILI", [])
393
    res = BiliBili(check_items=_check_items).main()
394
    send("Bilibili", res)
395