[
  {
    "path": ".gitignore",
    "content": "\n.DS_Store\n*.iml\n*.xml\n"
  },
  {
    "path": "README.md",
    "content": "# bilibili-tools\n\n挖坑开始\n\n此项目为 bilibili 主站各项功能实现\n\n另一已完成项目为 bilibili 直播站各功能实现 https://github.com/Dawnnnnnn/bilibili-live-tools\n\n目前已实现:\n\n    <!-- 风纪委员投票 -->\n    每日投币\n    每日登录\n    每日分享\n    每日观看\n\nQ:观看，分享，投币的视频如何选取?\n\nA:拉取关注列表，并在关注列表里 up 主投稿中随机选几个视频\n\nQ:如何关闭自己不想要的功能?\n\nA:\n\n>\n\n    tasks2 = [\n        # judge().coin_run(),   # 投币任务\n        judge().share_run(),  # 分享任务\n        judge().watch_run(),  # 观看任务\n        judge().judge_run()   # 仲裁案件]\n\n将你不想开启的功能删掉或者注释掉即可\n\n默认不打开投币功能，如想快速提高主站等级，把那一行注释去掉就可以了\n\n挖坑结束，后期完善一下 issue 里提到的案件仲裁问题就没事了。\n\n懒的加那个投票阙值了。。。。案件仲裁直接删了....还想用的话就用上一个版本。。\n"
  },
  {
    "path": "login.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n# @Time    : 2019/9/16 22:19\n# @Author  : Dawnnnnnn\n# @Contact: 1050596704@qq.com\nimport base64\nimport random\nimport requests\nimport rsa\nimport string\nfrom urllib import parse\nimport hashlib\n\n# temporary app parameter\nappkey = '4409e2ce8ffd12b8'\nbuild = '101800'\n# device = 'android_tv_yst'\nmobi_app = 'android_tv_yst'\napp_secret = '59b43e04ad6965f34319062b478f83dd'\n\n\nclass BiliLogin:\n    ua = \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\"\n\n    def __init__(self):\n        self.cookie = \"\"\n        self.access_token = \"\"\n\n    def post(self, url, data=None, headers=None, json=None, decode=True,\n             timeout=10):\n        try:\n            response = requests.post(url, data=data, headers=headers,\n                                     json=json,\n                                     timeout=timeout)\n            return response.json() if decode else response.content\n        except:\n            return None\n\n    def get(self, url, headers=None, decode=True, timeout=10):\n        try:\n            response = requests.get(url, headers=headers, timeout=timeout)\n            return response.json() if decode else response.content\n        except:\n            return None\n\n    def getSign(self, param):\n        salt = \"59b43e04ad6965f34319062b478f83dd\"\n        signHash = hashlib.md5()\n        signHash.update(f\"{param}{salt}\".encode())\n        return signHash.hexdigest()\n\n    def access_token_2_cookies(self, access_token):\n        params = f\"access_key={access_token}&appkey={appkey}&gourl=https%3A%2F%2Faccount.bilibili.com%2Faccount%2Fhome\"\n        url = f\"https://passport.bilibili.com/api/login/sso?{params}&sign={self.getSign(params)}\"\n        response = requests.get(url, allow_redirects=False)\n        return response.cookies.get_dict(domain=\".bilibili.com\")\n\n    # 登录\n    def login(self, username, password):\n        self.username, self.password = username, password\n        appKey = \"4409e2ce8ffd12b8\"\n        url = \"https://passport.snm0516.aisee.tv/api/oauth2/getKey\"\n        data = {'appkey': appKey,\n                'sign': self.getSign(f\"appkey={appKey}\")}\n        response = self.post(url, data=data)\n        if response and response.get('code') == 0:\n            keyHash = response['data']['hash']\n            pubKey = rsa.PublicKey.load_pkcs1_openssl_pem(\n                response['data']['key'].encode())\n        else:\n            print(f\"Key获取失败 {response}\")\n            return False\n        url = \"https://passport.snm0516.aisee.tv/api/tv/login\"\n        param = f\"appkey={appkey}&build={build}&captcha=&channel=master&guid=XYEBAA3E54D502E37BD606F0589A356902FCF&mobi_app={mobi_app}&password={parse.quote_plus(base64.b64encode(rsa.encrypt(f'{keyHash}{self.password}'.encode(), pubKey)))}&platform=android&token=5598158bcd8511e2&ts=0&username={parse.quote_plus(self.username)}\"\n        data = f\"{param}&sign={self.getSign(param)}\"\n        headers = {'Content-type': \"application/x-www-form-urlencoded\"}\n        response = self.post(url, data=data, headers=headers)\n        while response and response.get('code') == -105:\n            self.cookie = f\"sid={''.join(random.choices(string.ascii_lowercase + string.digits, k=8))}\"\n            url = \"https://passport.snm0516.aisee.tv/api/captcha?token=5598158bcd8511e2\"\n            headers = {'Cookie': self.cookie,\n                       'Host': \"snm0516.aisee.tv\",\n                       'User-Agent': BiliLogin.ua}\n            response = self.get(url, headers=headers, decode=False)\n            if response is None:\n                continue\n            url = \"http://106.75.36.27:19951/captcha/v1\"\n            img = base64.b64encode(response)\n            img = str(img, encoding=\"utf-8\")\n            json = {'image': img}\n            response = self.post(url, json=json, decode=True)\n            print(f\"验证码识别结果为: {response['message']}\")\n            url = \"https://passport.snm0516.aisee.tv/api/tv/login\"\n            param = f\"appkey={appKey}&captcha={response['message']}&channel=master&guid=XYEBAA3E54D502E37BD606F0589A356902FCF&mobi_app={mobi_app}&password={parse.quote_plus(base64.b64encode(rsa.encrypt(f'{keyHash}{self.password}'.encode(), pubKey)))}&platform=android&token=5598158bcd8511e2&ts=0&username={parse.quote_plus(self.username)}\"\n            data = f\"{param}&sign={self.getSign(param)}\"\n            headers = {'Content-type': \"application/x-www-form-urlencoded\",\n                       'Cookie': self.cookie}\n            response = self.post(url, data=data, headers=headers)\n        if response and response.get('code') == 0:\n            cookie_info = self.access_token_2_cookies(response['data']['token_info']['access_token'])\n            for key, value in cookie_info.items():\n                self.cookie = self.cookie + key + \"=\" + value + \";\"\n\n            self.access_token = response['data']['token_info']['access_token']\n            print(f\"{self.username}登录成功 {self.cookie} {self.access_token}\")\n            with open(\"cookies.txt\", \"a+\", encoding=\"utf-8\")as f:\n                f.write(f\"{self.username}----{self.cookie}----{self.access_token}\\n\")\n            return self.username, self.cookie, self.access_token\n        else:\n            print(f\"{self.username}登录失败 {response}\")\n"
  },
  {
    "path": "main.py",
    "content": "import random\nimport asyncio\nimport requests\nimport time\nimport json\nimport hashlib\nimport rsa\nimport base64\nimport re\nimport datetime\nfrom urllib import parse\nfrom login import BiliLogin\n\n\ndef CurrentTime():\n    currenttime = str(int(time.mktime(datetime.datetime.now().timetuple())))\n    return currenttime\n\n\nclass login():\n    cookies = \"\"\n    username = input(\"输入用户名:\")\n    password = input(\"输入密码:\")\n    headers = {\n        \"Host\": \"api.bilibili.com\",\n        \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\",\n        \"Accept-Language\": \"zh-CN,zh;q=0.9,en;q=0.8\",\n        \"Cookie\": cookies\n    }\n    csrf = \"\"\n    uid = \"\"\n    access_key = \"\"\n\n    async def calc_sign(self, str):\n        str = str + \"560c52ccd288fed045859ed18bffd973\"\n        hash = hashlib.md5()\n        hash.update(str.encode('utf-8'))\n        sign = hash.hexdigest()\n        return sign\n\n    async def get_pwd(self, username, password):\n        url = 'https://passport.bilibili.com/api/oauth2/getKey'\n        temp_params = 'appkey=1d8b6e7d45233436'\n        sign = await self.calc_sign(temp_params)\n        params = {'appkey': '1d8b6e7d45233436', 'sign': sign}\n        response = requests.post(url, data=params)\n        value = response.json()['data']\n        key = value['key']\n        Hash = str(value['hash'])\n        pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(key.encode())\n        password = base64.b64encode(rsa.encrypt(\n            (Hash + password).encode('utf-8'), pubkey))\n        password = parse.quote_plus(password)\n        username = parse.quote_plus(username)\n        return username, password\n\n    def login(self):\n        name, login.cookies, login.access_key = BiliLogin().login(login.username, login.password)\n\n        s1 = re.findall(r'bili_jct=(\\S+)', login.cookies, re.M)\n        s2 = re.findall(r'DedeUserID=(\\S+)', login.cookies, re.M)\n        login.headers = {\n            \"Host\": \"api.bilibili.com\",\n            \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\",\n            \"Accept-Language\": \"zh-CN,zh;q=0.9,en;q=0.8\",\n            \"Cookie\": login.cookies\n        }\n        login.csrf = (s1[0]).split(\";\")[0]\n        login.uid = (s2[0].split(\";\")[0])\n\n\nclass judge(login):\n\n    def randomint(self):\n        return ''.join(str(random.choice(range(10))) for _ in range(17))\n\n    def CurrentTime(self):\n        millis = int((time.time() * 1000))\n        return str(millis)\n\n    async def query_reward(self):\n        url = \"https://account.bilibili.com/home/reward\"\n        headers = {\n            \"Referer\": \"https://account.bilibili.com/account/home\",\n            \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\",\n            \"Cookie\": login.cookies\n        }\n        response = requests.get(url, headers=headers)\n        iflogin = response.json()['data']['login']\n        ifwatch_av = response.json()['data']['watch_av']\n        ifshare_av = response.json()['data']['share_av']\n        ifgive_coin = response.json()['data']['coins_av']\n        return [iflogin, ifwatch_av, ifshare_av, int(ifgive_coin)]\n\n    async def get_attention(self):\n        top50_attention_list = []\n        url = \"https://api.bilibili.com/x/relation/followings?vmid=\" + \\\n              str(login.uid) + \"&ps=50&order=desc\"\n        headers = {\n            \"Host\": \"api.bilibili.com\",\n            \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\",\n            \"Accept-Language\": \"zh-CN,zh;q=0.9,en;q=0.8\",\n            \"Cookie\": login.cookies\n        }\n        response = requests.get(url, headers=headers)\n        checklen = len(response.json()['data']['list'])\n        for i in range(0, checklen):\n            uids = (response.json()['data']['list'][i]['mid'])\n            top50_attention_list.append(uids)\n        return top50_attention_list\n\n    async def getsubmit_video(self):\n        top50_attention_list = await self.get_attention()\n        video_list = []\n        for mid in top50_attention_list:\n            url = \"https://space.bilibili.com/ajax/member/getSubmitVideos?mid=\" + \\\n                  str(mid) + \"&pagesize=100&tid=0\"\n            response = requests.get(url)\n            datalen = len(response.json()['data']['vlist'])\n            for i in range(0, datalen):\n                aid = response.json()['data']['vlist'][i]['aid']\n                video_list.append(aid)\n        return video_list\n\n    async def givecoin(self):\n        video_list = await self.getsubmit_video()\n        url = \"https://api.bilibili.com/x/web-interface/coin/add\"\n        aid = video_list[random.randint(0, len(video_list))]\n        data = {\n            \"aid\": aid,\n            \"multiply\": \"1\",\n            \"cross_domain\": \"true\",\n            \"csrf\": login.csrf\n        }\n        headers = {\n            \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\",\n            \"Referer\": \"https://www.bilibili.com/video/av\" + str(aid),\n            \"Origin\": \"https://www.bilibili.com\",\n            \"Host\": \"api.bilibili.com\",\n            \"Cookie\": login.cookies\n        }\n        response = requests.post(url, data=data, headers=headers)\n        print(\"coin_task:\", response.text)\n\n        if response.json()['code'] != 0:\n            await self.givecoin()\n        await asyncio.sleep(10)\n\n    async def get_cid(self, aid):\n        url = \"https://www.bilibili.com/widget/getPageList?aid=\" + str(aid)\n        response = requests.get(url)\n        cid = response.json()[0]['cid']\n        return cid\n\n    async def share(self):\n        video_list = await self.getsubmit_video()\n        aid = video_list[random.randint(0, len(video_list))]\n        url1 = \"https://app.bilibili.com/x/v2/view/share/add\"\n        headers = {\n            \"User-Agent\": \"Mozilla/5.0 BiliDroid/5.26.3 (bbcallen@gmail.com)\",\n            \"Host\": \"app.bilibili.com\",\n            \"Cookie\": \"sid=8wfvu7i7\"\n        }\n        ts = CurrentTime()\n        temp_params = \"access_key=\" + login.access_key + \"&aid=\" + \\\n                      str(\n                          aid) + \"&appkey=1d8b6e7d45233436&build=5260003&from=7&mobi_app=android&platform=android&ts=\" + str(\n            ts)\n        sign = await self.calc_sign(temp_params)\n        data = {\n            \"access_key\": login.access_key,\n            \"aid\": aid,\n            \"appkey\": \"1d8b6e7d45233436\",\n            \"build\": \"5260003\",\n            \"from\": \"7\",\n            \"mobi_app\": \"android\",\n            \"platform\": \"android\",\n            \"ts\": ts,\n            \"sign\": sign\n        }\n        response = requests.post(url1, headers=headers, data=data)\n        print(\"分享视频:\", response.json())\n\n    async def watch_av(self, aid, cid):\n        url = \"https://api.bilibili.com/x/report/web/heartbeat\"\n        headers = {\n            \"Host\": \"api.bilibili.com\",\n            \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\",\n            \"Referer\": \"https://www.bilibili.com/video/av\" + str(aid),\n            \"Cookie\": login.cookies\n        }\n        data = {\n            \"aid\": aid,\n            \"cid\": cid,\n            \"mid\": login.uid,\n            \"csrf\": login.csrf,\n            \"played_time\": \"0\",\n            \"realtime\": \"0\",\n            \"start_ts\": self.CurrentTime(),\n            \"type\": \"3\",\n            \"dt\": \"2\",\n            \"play_type\": \"1\"\n        }\n\n        response = requests.post(url, headers=headers, data=data)\n\n        print(\"watch_Av_state:\", response.text)\n\n    async def coin_run(self):\n        while 1:\n            try:\n                i = await self.query_reward()\n                coin_exp = i[3]\n                while coin_exp < 50:\n                    await self.givecoin()\n                    coin_exp = coin_exp + 10\n                if coin_exp == 50:\n                    print(\"投币任务完成\")\n                    await asyncio.sleep(86400)\n                    await self.coin_run()\n            except:\n                print(\"coin_run出错\")\n\n    async def share_run(self):\n        while 1:\n            try:\n                await self.share()\n                print(\"分享任务完成\")\n                await asyncio.sleep(21600)\n            except:\n                print(\"share_run出错\")\n\n    async def watch_run(self):\n        while 1:\n            try:\n                video_list = await self.getsubmit_video()\n                aid = video_list[random.randint(0, len(video_list))]\n                cid = await self.get_cid(aid)\n                await self.watch_av(aid, cid)\n                await asyncio.sleep(21600)\n            except:\n                print(\"watch_run出错\")\n\n\njudge().login()\n\nloop = asyncio.get_event_loop()\n\ntasks2 = [\n    judge().coin_run(),\n    judge().share_run(),\n    judge().watch_run(),\n\n]\nloop.run_until_complete(asyncio.wait(tasks2))\n"
  }
]