Exemple #1
0
    def post(self, request, *args, **kwargs):
        """
        post will handle the endpoint that allow a group admin to
              create and send an invite to a user to join his group

        endpoint : api/groups/:id/members/invite/
        """
        group = self.get_object()
        to_be_member = request.data.get("username")
        try:
            user = User.objects.get(username=to_be_member)
        except User.DoesNotExist:
            return Response(data={
                "message":
                "The User you wanted to add as member doesnt exist"
            },
                            status=status.HTTP_400_BAD_REQUEST)
        membership = Membership.objects.create(group=group,
                                               user=user,
                                               status='I')
        encrypted_details = encrypt(str(membership.id), SECRET_KEY)
        url = "{}/api/groups/members/invite/accept/{}/".format(
            DOMAIN, encrypted_details.decode())
        group_invite = "<h3>Dear {}, you have been invited by {}, to join the esusu group {} on Esusu confam<a href='{}'>Esusu confam</a>!</h3><br />Please kindly click on the url  to accept and activate your membership.{} May the force be with you!".format(
            user.username, group.admin.username, group.name, DOMAIN, url)
        logger.info("invite details: {}".format({
            "invite url": url,
            "user": user.username,
            "email": user.email
        }))
        mail_subject = "Esusu Group Invite"
        text_heading = "Hello, Dear"
        mail_resp = send_mail(mail_subject, user, text_heading, group_invite)
        logger.debug("email response : {}".format(mail_resp.json()))
        return Response(data={"url": url}, status=status.HTTP_201_CREATED)
Exemple #2
0
 def store(self, obj: object) -> str:
     """储存一个对象,返回其 key"""
     hash_str = str(id(obj))
     key = md5(hash_str.encode("utf-8")).hexdigest()
     if key not in self._db:
         logger.debug(f"Store {obj} -> {key}")
         self._db[key] = obj
     return key
Exemple #3
0
    def get(self, request, token):

        try:
            data = int(decrypt(token, SECRET_KEY).decode())
            membership = Membership.objects.get(id=int(data))
        except (ValueError, Membership.DoesNotExist) as e:
            logger.debug("something went wrong: {}".format(e.__str__()))
            return Response(status=status.HTTP_400_BAD_REQUEST)
        membership.status = 'A'
        membership.save()
        return Response(status=status.HTTP_200_OK)
Exemple #4
0
 def head(url: str, params=None, allow_redirects=True, **kwargs) -> requests.Response:
     """封装 HEAD 方法, 默认开启 302 重定向, 用于获取目标直链"""
     try:
         logger.debug(f"url: {url}, params: {params}, allow_redirects: {allow_redirects}")
         kwargs.setdefault("timeout", 10)
         kwargs.setdefault("headers", HtmlParseHelper._headers)
         return requests.head(url, params=params, verify=False, allow_redirects=allow_redirects, **kwargs)
     except requests.Timeout as e:
         logger.warning(e)
         return requests.Response()
     except requests.RequestException:
         return requests.Response()
Exemple #5
0
 def get(url: str, params=None, html_encoding="utf-8", **kwargs) -> requests.Response:
     """封装 GET 方法, 默认网页编码为 utf-8"""
     try:
         logger.debug(f"url: {url}, params: {params}")
         kwargs.setdefault("timeout", 5)
         kwargs.setdefault("headers", HtmlParseHelper._headers)
         ret = requests.get(url, params, verify=False, **kwargs)
         ret.encoding = html_encoding  # 有些网页仍然使用 gb2312/gb18030 之类的编码, 需要单独设置
         return ret
     except requests.Timeout as e:
         logger.warning(e)
         return requests.Response()
     except requests.RequestException:
         return requests.Response()
Exemple #6
0
 def post(url: str, data=None, html_encoding="utf-8", **kwargs) -> requests.Response:
     """"封装 POST 方法, 默认网页编码为 utf-8"""
     try:
         logger.debug(f"url: {url}, data: {data}")
         kwargs.setdefault("timeout", 5)
         kwargs.setdefault("headers", HtmlParseHelper._headers)
         ret = requests.post(url, data, verify=False, **kwargs)
         ret.encoding = html_encoding
         return ret
     except requests.Timeout as e:
         logger.warning(e)
         return requests.Response()
     except requests.RequestException:
         return requests.Response()
Exemple #7
0
 def get_real_url(self):
     """通过视频的 play_id 获取视频链接"""
     play_api = "http://service-agbhuggw-1259251677.gz.apigw.tencentcs.com/android/video/newplay"
     play_id = self.get_raw_url()
     secret_key = "zandroidzz"
     now = int(time.time() * 1000)  # 13 位时间戳
     sing = secret_key + str(now)
     sing = md5(sing.encode("utf-8")).hexdigest()
     logger.info(f"Parsing real url for {play_id}")
     payload = {"playid": play_id, "userid": "", "apptoken": "", "sing": sing, "map": now}
     resp = self.post(play_api, data=payload)
     if resp.status_code != 200:
         logger.warning(f"Response error: {resp.status_code} {play_api}")
         logger.debug(f"POST params: {payload}")
         return "error"
     real_url = resp.json()["data"]["videoplayurl"]
     logger.info(f"Video real url: {real_url}")
     return real_url
Exemple #8
0
    def put(self, request, *args, **kwargs):
        user_id = request.data.get("user_id")
        if user_id is None:
            return Response(data={"message": "a user is required to be added"},
                            status=status.HTTP_400_BAD_REQUEST)
        try:
            grp = self.get_object()
        except Group.DoesNotExist:
            return Response(
                data={"message": "The requested group does not exist"},
                status=status.HTTP_404_NOT_FOUND)
        try:
            usr = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return Response(data={
                "message":
                "The User you wanted to add as member doesnt exist"
            },
                            status=status.HTTP_400_BAD_REQUEST)
        mbr = grp.members.all().filter(user__id=usr.id)

        if len(mbr) > 0:
            return Response(
                data={"message": "The User is already a member of this group"},
                status=status.HTTP_400_BAD_REQUEST)
        membership = Membership.objects.create(group=grp, user=usr, status="A")
        membership.save()
        logger.debug(membership)
        grp.members.add(membership)
        mbr = [i.user.username for i in grp.members.all()]
        if self.check_group_is_ready():
            tenure = Tenure.objects.create(group=grp)
            return Response(data={
                "message":
                "The amount of active " +
                "members are complete and the tenure" +
                " should start now, below is the sequence of collection",
                "collections":
                tenure.collection_sequences
            },
                            status=status.HTTP_200_OK)

        return Response(data={"members": mbr}, status=status.HTTP_201_CREATED)
Exemple #9
0
    def get_real_url(self) -> str:
        url = "http://www.yhdm.tv/" + self.get_raw_url()
        logger.info(f"Parsing real url for {url}")
        resp = self.get(url)
        if resp.status_code != 200:
            logger.warning(f"Response error: {resp.status_code} {url}")
            return "error"
        video_url = self.xpath(
            resp.text, '//div[@id="playbox"]/@data-vid')[0]  # "url$format"
        video_url = video_url.split(
            "$"
        )[0]  # "http://quan.qq.com/video/1098_ae4be38407bf9d8227748e145a8f97a5"
        if not video_url.startswith("http"):  # 偶尔出现一些无效视频
            logger.warning(f"This video is not valid: {video_url}")
            return "error"

        logger.debug(f"Redirect for {video_url}")
        resp = self.head(video_url, allow_redirects=True)  # 获取直链时会重定向 2 次
        logger.info(f"Video real url: {resp.url}")
        return resp.url  # 重定向之后的视频直链
Exemple #10
0
 def set_cookie(self):
     # 计算 k2 的值
     # https://www.agefans.tv/age/static/js/s_runtimelib.js?ver=202008211700   __getplay_pck()
     t1 = self._client.cookies.get("t1")
     logger.debug(f"Get cookie t1={t1}")
     t = (int(t1) // 1000) >> 5
     k2 = (t * (t % 4096) + 39382) * (t % 4096) + t
     k2 = str(k2)
     # 计算 t2 的值, 生成一个后三位包含 k2 最后一位的数时间戳
     # https://www.agefans.tv/age/static/js/s_dett.js?ver=202008211700   __getplay_pck2()
     k2_last = k2[-1]
     t2 = ""
     while True:
         now = str(int(time.time() * 1000))
         last_3w = now[-3:]
         if 0 <= last_3w.find(k2_last):
             t2 = now
             break
     logger.debug(f"Set cookies, k2={k2}, t2={t2}")
     self._client.cookies.update({"k2": k2, "t2": t2})
Exemple #11
0
 def post(self, request, *args, **kwargs):
     """
     post:  process the log in request
     """
     username = request.data.get("username", "")
     password = request.data.get("password", "")
     logger.debug("log in credentials",
                  extra={
                      "username": username,
                      "password": password
                  })
     user = BasicAuthenticationBackend().authenticate(request=request,
                                                      username=username,
                                                      password=password)
     if user is not None:
         login(request, user)
         serializer = TokenSerializer(
             data={"token": jwt_encode_handler(jwt_payload_handler(user))})
         serializer.is_valid()
         return Response(serializer.data)
     return Response(status=status.HTTP_401_UNAUTHORIZED)
Exemple #12
0
    def post(self, request, *args, **kwargs):
        grp = self.get_object()
        user = request.user
        mbr = Membership.objects.create(group=grp, user=user, status="I")
        mbr.save()
        grp.members.add(mbr)

        mbrship_request = "<h3>Dear {}, a user just requested to join your co-operative group on Esusu confam, kindly log in to accept!".format(
            grp.admin.username)
        logger.info("new member details: name: {}, email: {}".format(
            user.username, user.email))
        mail_subject = "Esusu Group Membership request"
        text_heading = "Hello, Dear"
        mail_resp = send_mail(mail_subject, grp.admin, text_heading,
                              mbrship_request)
        logger.debug("email response : {}".format(mail_resp.json()))
        Response(data={
            "message":
            "A request has been sent to the group admin to confirm your membership. thanks"
        },
                 status=status.HTTP_201_CREATED)
Exemple #13
0
 def search(self, keyword: str) -> List[DanmakuMetaInfo]:
     """搜索番剧信息"""
     logger.info(f"Searching for danmaku: {keyword}")
     ret = []
     params = {"keyword": keyword, "search_type": "media_bangumi"}
     params2 = {
         "keyword": keyword,
         "search_type": "video",
         "tids": 13,
         "order": "dm",
         "page": 1,
         "duration": 4
     }
     task_list = [
         (self.get, (self._search_api, params), {}),
         (self.get, (self._search_api, params2), {}
          )  # 用户上传的60 分钟以上的视频, 按弹幕数量排序
     ]
     resp_list = self.submit_tasks(task_list)  # 多线程同时搜索
     for resp in resp_list:
         if resp.status_code != 200:
             continue
         data = resp.json()
         if data["code"] != 0 or data["data"]["numResults"] == 0:
             continue
         for item in data["data"]["result"]:
             if '<em class="keyword">' not in item[
                     "title"]:  # 没有匹配关键字, 是B站的推广视频
                 continue
             dm_mate = DanmakuMetaInfo()
             dm_mate.title = item["title"].replace(r'<em class="keyword">',
                                                   "").replace("</em>",
                                                               "")  # 番剧标题
             dm_mate.play_page_url = item.get("goto_url") or item.get(
                 "arcurl")  # 番剧播放页链接
             dm_mate.num = int(item.get("ep_size") or -1)
             logger.debug(f"Match danmaku: {dm_mate}")
             ret.append(dm_mate)
     return ret
Exemple #14
0
    def get_real_url(self):

        headers = {
            "User-Agent":
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4033.0 Safari/537.36 Edg/81.0.403.1",
            "Referer": self._base_url
        }

        play_page_url = self._base_url + self.get_raw_url(
        )  # "https://www.agefans.tv/play/20170172?playid=1_1"
        logger.info(f"Parse page: {play_page_url}")
        aid = play_page_url.split("?")[0].split("/")[-1]
        playindex, epindex = play_page_url.split("=")[-1].split("_")
        params = {
            "aid": aid,
            "playindex": playindex,
            "epindex": epindex,
            "r": random()
        }

        self._client.head(play_page_url,
                          headers=headers)  # 接受服务器设置的 cookie, 不需要 body, 加快速度
        self.set_cookie()  # 否则返回的数据与视频对不上
        resp = self._client.get(self._play_api,
                                params=params,
                                headers=headers,
                                verify=False)
        while "err:timeout" in resp.text:
            logger.debug("Response : err:timeout")
            self.set_cookie()
            resp = self._client.get(self._play_api,
                                    params=params,
                                    headers=headers,
                                    verify=False)
        logger.debug(resp.status_code)
        logger.debug(resp.text)
        try:
            data = resp.json()
            real_url = data["purlf"] + data["vurl"]
            real_url = real_url.split("?")[-1].replace("url=", "")
            real_url = requests.utils.unquote(real_url)
            if real_url.startswith("//"):
                real_url = "http:" + real_url
            logger.debug(f"real_url={real_url}")
        except Exception:
            return "error, try agin"
        return real_url
Exemple #15
0
    def detect_video_format(self) -> str:
        """判断视频真正的格式, url 可能没有视频后缀"""
        # 尝试从 url 提取后缀
        url = self._get_real_url()
        try:
            ext = url.split("?")[0].split(".")[-1].lower()
            if ext in ["mp4", "flv"]:
                return ext
            if ext == "m3u8":
                return "hls"
        except (IndexError, AttributeError):
            pass

        # 视频的元数据中包含了视频的格式信息, 在视频开头寻找十六进制标识符推断视频格式
        format_hex = {
            "mp4": ["69736F6D", "70617663", "6D703432", "4D50454734", "4C617666"],
            "flv": ["464C56"],
            "hls": ["4558544D3355"]
        }

        _, data_iter = self._get_stream_from_server(0, 512)
        if not data_iter:
            logger.warning("Could not get video stream from server")
            return "unknown"

        logger.debug("Detecting video format from binary stream")
        video_meta = next(data_iter).hex().upper()
        for format_, hex_list in format_hex.items():
            for hex_sign in hex_list:
                if hex_sign in video_meta:
                    logger.debug(f"Video format: {format_}")
                    return format_
        logger.error("Could not detect video format from stream")
        logger.debug("Video raw binary stream (512byte):")
        logger.debug(video_meta)
        return "unknown"
Exemple #16
0
 def update(self, key: str, value: object):
     if key in self._db:
         logger.debug(f"Update {key} -> {value}")
         self._db[key] = value
     return key
Exemple #17
0
 def fetch(self, key: str):
     ret = self._db.get(key)
     logger.debug(f"Fetch {key} -> {ret}")
     return ret
Exemple #18
0
 def post(self, request, *args, **kwargs):
     serializer = UserSerializer(data=request.data)
     logger.debug(request.data)
     serializer.is_valid(raise_exception=True)
     serializer.save()
     return Response(status=status.HTTP_201_CREATED)
Exemple #19
0
 def _get_real_url(self):
     """获取视频直链, 如果有缓存的话, 使用缓存的值"""
     if self._real_url:  # 缓存解析完成的直链, 防止重复解析
         logger.debug(f"Using cached real url: {self._real_url}")
         return self._real_url
     return self.get_real_url()