Exemple #1
0
 async def test_aggregate_sum_different_field_type_at_left_with_f_expression(self):
     with self.assertRaisesRegex(
         FieldError, "Cannot use arithmetic expression between different field type"
     ):
         await testmodels.DecimalFields.all().annotate(
             sum_decimal=Sum(F("id") + F("decimal"))
         ).values("sum_decimal")
Exemple #2
0
async def payment(pay: PayIn):
    """
    계좌 이체 기능입니다.
    기존에 자신과 보낼 사람의 데이터를 입력받고 처리하는 역할을 수행합니다.
    """
    # 액수가 부족한지 검사하기
    transfer_account = await Accounts.get(customer_email_id=pay.transfer_email)

    if transfer_account.balance < pay.amount:
        raise HTTPException(status_code=400, detail='잔액이 부족해서 이체 불가능')
    # 돈 보내는 트랜잭션 + 기록
    try:
        async with in_transaction() as connection:
            await Accounts.filter(customer_email_id=pay.transfer_email
                                  ).update(balance=F('balance') - pay.amount)
            await Accounts.filter(customer_email_id=pay.deposit_email
                                  ).update(balance=F('balance') + pay.amount)
            transcation_data = await Transcation.create(
                amount=pay.amount,
                transfer_email_id=pay.transfer_email,
                deposit_email_id=pay.deposit_email,
                trans_type_id='일반이체',
                using_db=connection,
            )
    except OperationalError:
        raise HTTPException(status_code=400, detail='이체 도중 문제가 생겼습니다.')
    # 출력
    return await Transcations_Pydantic.from_tortoise_orm(transcation_data)
Exemple #3
0
 async def test_filter_with_f_expression(self):
     await IntFields.create(intnum=1, intnum_null=1)
     await IntFields.create(intnum=2, intnum_null=1)
     self.assertEqual(await IntFields.filter(intnum=F("intnum_null")).count(), 1)
     self.assertEqual(await IntFields.filter(intnum__gte=F("intnum_null")).count(), 2)
     self.assertEqual(
         await IntFields.filter(intnum=F("intnum_null") + F("intnum_null")).count(), 1
     )
Exemple #4
0
async def increase_sent_count(
    uuid_: str,
    sent_ios: int = 0,
    sent_android: int = 0,
) -> int:
    return await Notification.filter(
        uuid=uuid_
    ).update(
        sent_ios=F('sent_ios') + sent_ios,
        sent_android=F('sent_android') + sent_android,
    )
Exemple #5
0
    async def put(self):
        """Изменяет этап приготовления"""
        user_id = int(await check_authorized(self.request))
        if not await permits(self.request, "is_active"):
            raise web.HTTPForbidden

        try:
            async with in_transaction():
                recipe = await Recipe.get_or_none(
                    pk=int(self.request.match_info["recipe_id"]))
                order = int(self.request.match_info["order"])
                step = await CookingStep.get_or_none(recipe=recipe,
                                                     order=order).only("id")
        except ValueError:
            raise web.HTTPBadRequest

        if not recipe or not step:
            raise web.HTTPNotFound

        await recipe.fetch_related("author")
        if recipe.author.id != user_id:
            raise web.HTTPForbidden

        try:
            json = await self.request.json()
        except JSONDecodeError:
            raise web.HTTPBadRequest

        try:
            async with in_transaction():
                if "order" in json:
                    if json["order"] < order:
                        await CookingStep.filter(
                            recipe=recipe,
                            order__gte=json["order"],
                            order__lt=order).update(order=F("order") + 1)
                    elif json["order"] > order:
                        await CookingStep.filter(
                            recipe=recipe,
                            order__gt=order,
                            order__lte=json["order"]).update(order=F("order") -
                                                             1)
                await CookingStep.filter(pk=step.pk).update(**json)
        except (KeyError, IntegrityError, ConfigurationError) as e:
            raise web.HTTPBadRequest(reason=e)

        raise web.HTTPNoContent(
            headers={
                "Location": str(self.request.url /
                                str(json.get("order", order)))
            })
 async def test_f_expression(self):
     obj0 = await testmodels.DecimalFields.create(
         decimal=Decimal("1.23456"), decimal_nodec=18.7)
     await obj0.filter(id=obj0.id
                       ).update(decimal=F("decimal") + Decimal("1"))
     obj1 = await testmodels.DecimalFields.get(id=obj0.id)
     self.assertEqual(obj1.decimal, Decimal("2.2346"))
Exemple #7
0
    async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
        """Refill user's balance via listening for reactions to messages from The Accountant bot"""

        if payload.user_id not in config.ACCOUNTANT_BOT_IDS:
            # we need to only refill balance if it was The Accountant bot who reacted to message
            return

        channel = self.bot.get_channel(payload.channel_id)
        message = await channel.fetch_message(payload.message_id)

        if (
            # if user tried to send points in message
            "!send" in message.content
            # and there were single mention in the message
            and len(message.raw_mentions) == 1
            # and lottery bot was mentioned
            and self.bot.user.id in message.raw_mentions
        ):
            await ensure_registered(message.author.id)
            # remove bot mention from content
            content_no_mentions = message.system_content.replace(str(self.bot.user.id), "")
            # remove comma from string (because of The Accountant Bot)
            content_no_mentions_no_comma = content_no_mentions.replace(",", "")
            # parse all numbers from message
            list_of_numbers = re.findall("\\d*[\\.]?\\d+", content_no_mentions_no_comma)
            # points should be the first number
            str_points = list_of_numbers[0]
            points = Decimal(str_points)
            await User.filter(id=message.author.id).update(balance=F("balance") + points)  # prevent race conditions
            await message.channel.send(
                f"<@{message.author.id}>, your balance was credited for {pp_points(points)}{config.POINTS_EMOJI}.\nTo participate, `/sweepstake buy [sweepstake name]`",  # noqa: E501
                delete_after=DELETE_AFTER,
            )
Exemple #8
0
    def get_update_sql(
        self,
        update_fields: Optional[Iterable[str]],
        arithmetic_or_function: Optional[Dict[str, Union[ArithmeticExpression,
                                                         Function]]],
    ) -> str:
        """
        Generates the SQL for updating a model depending on provided update_fields.
        Result is cached for performance.
        """
        key = ",".join(update_fields) if update_fields else ""
        if key in self.update_cache:
            return self.update_cache[key]
        arithmetic_or_function = arithmetic_or_function or {}
        table = self.model._meta.basetable
        query = self.db.query_class.update(table)
        count = 0
        for field in update_fields or self.model._meta.fields_db_projection.keys(
        ):
            db_column = self.model._meta.fields_db_projection[field]
            field_object = self.model._meta.fields_map[field]
            if not field_object.pk:
                if field not in arithmetic_or_function.keys():
                    query = query.set(db_column, self.parameter(count))
                    count += 1
                else:
                    value = F.resolver_arithmetic_expression(
                        self.model, arithmetic_or_function.get(field))[0]
                    query = query.set(db_column, value)

        query = query.where(
            table[self.model._meta.db_pk_column] == self.parameter(count))

        sql = self.update_cache[key] = query.get_sql()
        return sql
Exemple #9
0
    async def delete(self):
        """Удаляет этап приготовления"""
        user_id = int(await check_authorized(self.request))
        if not await permits(self.request, "is_active"):
            raise web.HTTPForbidden

        try:
            async with in_transaction():
                recipe = await Recipe.get_or_none(
                    pk=int(self.request.match_info["recipe_id"]))
                order = int(self.request.match_info["order"])
                step = await CookingStep.get_or_none(recipe=recipe,
                                                     order=order).only("id")
        except ValueError:
            raise web.HTTPBadRequest

        if not recipe or not step:
            raise web.HTTPNotFound

        await recipe.fetch_related("author")
        if recipe.author.id != user_id:
            raise web.HTTPForbidden

        async with in_transaction():
            await step.delete()
            await CookingStep.filter(
                recipe=recipe, order__gt=order).update(order=F("order") - 1)

        raise web.HTTPNoContent()
Exemple #10
0
 async def test_aggregate_sum_no_exist_field_with_f_expression(self):
     with self.assertRaisesRegex(
             FieldError,
             "There is no non-virtual field not_exist on Model DecimalFields",
     ):
         await testmodels.DecimalFields.all().annotate(
             sum_decimal=Sum(F("not_exist"))).values("sum_decimal")
Exemple #11
0
    async def post(self):
        """Добавляет этап приготовления"""
        user_id = int(await check_authorized(self.request))
        if not await permits(self.request, "is_active"):
            raise web.HTTPForbidden

        try:
            recipe = await Recipe.get_or_none(
                pk=int(self.request.match_info["recipe_id"]))
        except ValueError:
            raise web.HTTPBadRequest

        if not recipe:
            raise web.HTTPNotFound

        await recipe.fetch_related("author")
        if recipe.author.id != user_id:
            raise web.HTTPForbidden

        try:
            json = await self.request.json()
        except JSONDecodeError:
            raise web.HTTPBadRequest

        try:
            async with in_transaction():
                await CookingStep.filter(
                    recipe=recipe,
                    order__gte=json["order"]).update(order=F("order") + 1)
                step = await CookingStep.create(recipe=recipe, **json)
        except (KeyError, IntegrityError, ConfigurationError) as e:
            raise web.HTTPBadRequest(reason=e)

        raise web.HTTPCreated(
            headers={"Location": str(self.request.url / str(step.order))})
Exemple #12
0
 async def test_annotate_order_expression(self):
     data = (
         await IntFields.annotate(idp=F("id") + 1)
         .order_by("-idp")
         .first()
         .values_list("id", "idp")
     )[0]
     self.assertEqual(data[0] + 1, data[1])
Exemple #13
0
    async def test_update_with_custom_function(self):
        class JsonSet(Function):
            def __init__(self, field: F, expression: str, value: Any):
                super().__init__("JSON_SET", field, expression, value)

        json = await JSONFields.create(data={})
        self.assertEqual(json.data_default, {"a": 1})

        json.data_default = JsonSet(F("data_default"), "$.a", 2)
        await json.save()

        json_update = await JSONFields.get(pk=json.pk)
        self.assertEqual(json_update.data_default, {"a": 2})

        await JSONFields.filter(pk=json.pk).update(
            data_default=JsonSet(F("data_default"), "$.a", 3))
        json_update = await JSONFields.get(pk=json.pk)
        self.assertEqual(json_update.data_default, {"a": 3})
Exemple #14
0
    async def test_aggregate_avg_with_f_expression(self):
        await testmodels.DecimalFields.create(decimal=Decimal("0"), decimal_nodec=1)
        await testmodels.DecimalFields.create(decimal=Decimal("9.99"), decimal_nodec=1)
        await testmodels.DecimalFields.create(decimal=Decimal("27.27"), decimal_nodec=1)
        values = (
            await testmodels.DecimalFields.all()
            .annotate(avg_decimal=Avg(F("decimal")))
            .values("avg_decimal")
        )
        self.assertEqual(
            values[0],
            {"avg_decimal": Decimal("12.42")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(avg_decimal=Avg(F("decimal") + 1))
            .values("avg_decimal")
        )
        self.assertEqual(
            values[0],
            {"avg_decimal": Decimal("13.42")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(avg_decimal=Avg(F("decimal") + F("decimal")))
            .values("avg_decimal")
        )
        self.assertEqual(
            values[0],
            {"avg_decimal": Decimal("24.84")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(avg_decimal=Avg(F("decimal") + F("decimal_nodec")))
            .values("avg_decimal")
        )
        self.assertEqual(
            values[0],
            {"avg_decimal": Decimal("13")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(avg_decimal=Avg(F("decimal") + F("decimal_null")))
            .values("avg_decimal")
        )
        self.assertEqual(
            values[0],
            {"avg_decimal": None},
        )
Exemple #15
0
    async def test_aggregate_max_with_f_expression(self):
        await testmodels.DecimalFields.create(decimal=Decimal("0"), decimal_nodec=1)
        await testmodels.DecimalFields.create(decimal=Decimal("9.99"), decimal_nodec=1)
        await testmodels.DecimalFields.create(decimal=Decimal("27.27"), decimal_nodec=1)
        values = (
            await testmodels.DecimalFields.all()
            .annotate(max_decimal=Max(F("decimal")))
            .values("max_decimal")
        )
        self.assertEqual(
            values[0],
            {"max_decimal": Decimal("27.27")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(max_decimal=Max(F("decimal") + 1))
            .values("max_decimal")
        )
        self.assertEqual(
            values[0],
            {"max_decimal": Decimal("28.27")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(max_decimal=Max(F("decimal") + F("decimal")))
            .values("max_decimal")
        )
        self.assertEqual(
            values[0],
            {"max_decimal": Decimal("54.54")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(max_decimal=Max(F("decimal") + F("decimal_nodec")))
            .values("max_decimal")
        )
        self.assertEqual(
            values[0],
            {"max_decimal": Decimal("28")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(max_decimal=Max(F("decimal") + F("decimal_null")))
            .values("max_decimal")
        )
        self.assertEqual(
            values[0],
            {"max_decimal": None},
        )
Exemple #16
0
    async def test_aggregate_sum_with_f_expression(self):
        await testmodels.DecimalFields.create(decimal=Decimal("0"), decimal_nodec=1)
        await testmodels.DecimalFields.create(decimal=Decimal("9.99"), decimal_nodec=1)
        await testmodels.DecimalFields.create(decimal=Decimal("27.27"), decimal_nodec=1)
        values = (
            await testmodels.DecimalFields.all()
            .annotate(sum_decimal=Sum(F("decimal")))
            .values("sum_decimal")
        )
        self.assertEqual(
            values[0],
            {"sum_decimal": Decimal("37.26")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(sum_decimal=Sum(F("decimal") + 1))
            .values("sum_decimal")
        )
        self.assertEqual(
            values[0],
            {"sum_decimal": Decimal("40.26")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(sum_decimal=Sum(F("decimal") + F("decimal")))
            .values("sum_decimal")
        )
        self.assertEqual(
            values[0],
            {"sum_decimal": Decimal("74.52")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(sum_decimal=Sum(F("decimal") + F("decimal_nodec")))
            .values("sum_decimal")
        )
        self.assertEqual(
            values[0],
            {"sum_decimal": Decimal("4E+1")},
        )

        values = (
            await testmodels.DecimalFields.all()
            .annotate(sum_decimal=Sum(F("decimal") + F("decimal_null")))
            .values("sum_decimal")
        )
        self.assertEqual(
            values[0],
            {"sum_decimal": None},
        )
Exemple #17
0
    async def test_refresh_from_db(self):
        int_field = await IntFields.create(intnum=1, intnum_null=2)
        int_field_in_db = await IntFields.get(pk=int_field.pk)
        int_field_in_db.intnum = F("intnum") + 1
        await int_field_in_db.save(update_fields=["intnum"])
        self.assertIsNot(int_field_in_db.intnum, 2)
        self.assertIs(int_field_in_db.intnum_null, 2)

        await int_field_in_db.refresh_from_db(fields=["intnum"])
        self.assertIs(int_field_in_db.intnum, 2)
        self.assertIs(int_field_in_db.intnum_null, 2)

        int_field_in_db.intnum = F("intnum") + 1
        await int_field_in_db.save()
        self.assertIsNot(int_field_in_db.intnum, 3)
        self.assertIs(int_field_in_db.intnum_null, 2)

        await int_field_in_db.refresh_from_db()
        self.assertIs(int_field_in_db.intnum, 3)
        self.assertIs(int_field_in_db.intnum_null, 2)
    async def test_AE_default(self):
        # AE: ArithmeticExpression
        category = Case(When(intnum__gte=8, then=8), default=F("intnum") + 1)
        sql = IntFields.all().annotate(category=category).values(
            "intnum", "category").sql()

        dialect = self.db.schema_generator.DIALECT
        if dialect == "mysql":
            expected_sql = "SELECT `intnum` `intnum`,CASE WHEN `intnum`>=8 THEN 8 ELSE `intnum`+1 END `category` FROM `intfields`"
        else:
            expected_sql = 'SELECT "intnum" "intnum",CASE WHEN "intnum">=8 THEN 8 ELSE "intnum"+1 END "category" FROM "intfields"'
        self.assertEqual(sql, expected_sql)
    async def test_F_default(self):
        category = Case(When(intnum__gte=8, then="big"),
                        default=F("intnum_null"))
        sql = IntFields.all().annotate(category=category).values(
            "intnum", "category").sql()

        dialect = self.db.schema_generator.DIALECT
        if dialect == "mysql":
            expected_sql = "SELECT `intnum` `intnum`,CASE WHEN `intnum`>=8 THEN 'big' ELSE `intnum_null` END `category` FROM `intfields`"
        else:
            expected_sql = 'SELECT "intnum" "intnum",CASE WHEN "intnum">=8 THEN \'big\' ELSE "intnum_null" END "category" FROM "intfields"'
        self.assertEqual(sql, expected_sql)
Exemple #20
0
    def resolve(self, model: "Type[Model]", table: Table) -> dict:
        """
        Used to resolve the Function statement for SQL generation.

        :param model: Model the function is applied on to.
        :param table: ``pypika.Table`` to keep track of the virtual SQL table
            (to allow self referential joins)
        :return: Dict with keys ``"joins"`` and ``"fields"``
        """

        if isinstance(self.field, str):
            function = self._resolve_field_for_model(model, table, self.field)
            function["field"] = self._get_function_field(function["field"], *self.default_values)
            return function

        field, field_object = F.resolver_arithmetic_expression(model, self.field)
        if self.populate_field_object:
            self.field_object = field_object
        return {"joins": [], "field": self._get_function_field(field, *self.default_values)}
Exemple #21
0
    def _make_query(self) -> None:
        table = self.model._meta.basetable
        self.query = self._db.query_class.update(table)
        self.resolve_filters(
            model=self.model,
            q_objects=self.q_objects,
            annotations=self.annotations,
            custom_filters=self.custom_filters,
        )
        # Need to get executor to get correct column_map
        executor = self._db.executor_class(model=self.model, db=self._db)

        for key, value in self.update_kwargs.items():
            field_object = self.model._meta.fields_map.get(key)
            if not field_object:
                raise FieldError(
                    f"Unknown keyword argument {key} for model {self.model}")
            if field_object.pk:
                raise IntegrityError(
                    f"Field {key} is PK and can not be updated")
            if isinstance(field_object,
                          (ForeignKeyFieldInstance, OneToOneFieldInstance)):
                fk_field: str = field_object.source_field  # type: ignore
                db_field = self.model._meta.fields_map[fk_field].source_field
                value = executor.column_map[fk_field](getattr(
                    value, field_object.to_field_instance.model_field_name),
                                                      None)
            else:
                try:
                    db_field = self.model._meta.fields_db_projection[key]
                except KeyError:
                    raise FieldError(
                        f"Field {key} is virtual and can not be updated")
                if isinstance(value, Term):
                    value = F.resolver_arithmetic_expression(
                        self.model, value)[0]
                elif isinstance(value, Function):
                    value = value.resolve(self.model, table)["field"]
                else:
                    value = executor.column_map[key](value, None)

            self.query = self.query.set(db_field, value)
Exemple #22
0
async def payday(amount: int):
    """
    월급을 주거나 세금을 전체다 걷어야할 때 사용합니다.
    음수로 값을 넣을 경우 음수로 작동합니다.
    관리자 또는 선생님의 권한을 가진 토큰이 필요합니다.
    """
    # 0 예외 처리
    if amount == 0:
        raise HTTPException(status_code=400, detail='0의 데이터는 입력을 받지 않습니다.')
    try:
        async with in_transaction() as connection:
            await Accounts.all().update(balance=F('balance') + amount)
            payday_data = await PayDay.create(
                amount=amount,
                trans_type_id='월급입금',
            )

    except OperationalError:
        raise HTTPException(status_code=400, detail='월급 주는 도중에 문제가 발생했습니다.')

    return await PayDay_Pydantic.from_tortoise_orm(payday_data)
 async def test_f_expression_save(self):
     obj1 = await self.model.create()
     obj1.number = F("number") + 1
     await obj1.save()
 async def test_f_expression(self):
     obj1 = await self.model.create(chars="aaa")
     await self.model.filter(eyedee=obj1.eyedee).update(chars=F("blip"))
     obj2 = await self.model.get(eyedee=obj1.eyedee)
     self.assertEqual(obj2.chars, "BLIP")
Exemple #25
0
 async def test_update_f_expression(self):
     obj0 = await IntFields.create(intnum=2147483647)
     await IntFields.filter(id=obj0.id).update(intnum=F("intnum") - 1)
     obj = await IntFields.get(id=obj0.id)
     self.assertEqual(obj.intnum, 2147483646)
Exemple #26
0
    async def _handle_payments_to_winners(self) -> bool:
        """Handle payments for winning tickets

        We will check if users have tickets with winning numbers, if they don't lottery points will
        be added to the total winning pool for the next lottery
        """
        striked_lotteries = (
            await Lottery.filter(status=LotteryStatus.STRIKED)
            .prefetch_related("tickets")
            .annotate(total_tickets=Count("tickets"))
        )
        notification_channel = self.bot.get_channel(config.LOTTERY_CHANNEL_ID)
        bulk_save_has_winners = []
        bulk_save_no_winners = []
        for lottery in striked_lotteries:
            # check if lottery has winning tickets
            winners_ids = set()
            winning_tickets = []
            for ticket in lottery.tickets:
                if ticket.ticket_number in lottery.winning_tickets:
                    winners_ids.add(ticket.user_id)
                    winning_tickets.append(ticket)
                    logging.debug(f":::lottery_cron: Winner for lottery: {lottery.name} is: {ticket.user_id}")
            # process winners
            if winning_tickets:
                bulk_save_has_winners.append(lottery.id)
                # get winning pool for the current lottery
                lottery_pool = lottery.total_tickets * lottery.ticket_price
                # get old winning pool
                old_winning_pool = await get_old_winning_pool()
                total_winning_pool = old_winning_pool + lottery_pool
                winning_ticket_share = total_winning_pool / len(winning_tickets)
                # share winning pool between winners
                for w_ticket in winning_tickets:
                    await User.filter(id__in=[w_ticket.user_id]).update(
                        balance=F("balance") + int(winning_ticket_share)
                    )
                # remove old winning pool (because it was paid to the winners)
                if old_winning_pool:
                    await Lottery.filter(Q(status=LotteryStatus.ENDED) & Q(has_winners=False)).update(has_winners=True)
                winners_mentions = [f"<@!{_}>" for _ in winners_ids]
                winners_mentions_str = ", ".join(winners_mentions)
            else:
                bulk_save_no_winners.append(lottery.id)
            widget = Embed(
                description=f"`{lottery.name}` striked",
                color=GOLD,
                title=lottery.name,
            )
            widget.set_thumbnail(url=config.PROJECT_THUMBNAIL)
            widget.add_field(
                name="Winning tickets:",
                value=f"`{', '.join(map(str, lottery.winning_tickets))}`" if lottery.winning_tickets else "`-`",
                inline=False,
            )
            if winners_ids:
                widget.add_field(
                    name=":trophy::trophy:Winners:trophy::trophy:", value=winners_mentions_str, inline=False
                )
                # send notification to the channel
                await notification_channel.send(content=winners_mentions_str, embed=widget)
            else:
                widget.add_field(
                    name="Winners:",
                    value="Nobody won the sweepstake, winning pool will be added to the next sweepstake",
                    inline=False,
                )
                # send notification to the channel
                await notification_channel.send(embed=widget)
        # bulk change lotteries to LotteryStatus.ENDED
        should_reload_options = False
        if bulk_save_has_winners:
            await Lottery.filter(id__in=bulk_save_has_winners).update(status=LotteryStatus.ENDED, has_winners=True)
            should_reload_options = True
        if bulk_save_no_winners:
            await Lottery.filter(id__in=bulk_save_no_winners).update(status=LotteryStatus.ENDED)
            should_reload_options = True
        return should_reload_options
 async def test_f_expression_save_update_fields(self):
     obj1 = await self.model.create()
     obj1.number = F("number") + 1
     await obj1.save(update_fields=["number"])
Exemple #28
0
async def detect_photo(message: types.Message):
    try:
        await dp.throttle("detect_photo", rate=30)
    except Throttled:
        await message.answer(
            "Подождите пару минут, перед тем как отправлять следующее фото!"
        )
        return

    user = await User.filter(user_id=message.from_user.id).first()
    if user is None:
        user = User(user_id=message.from_user.id)
    elif user.usages <= 0:
        await message.answer("У вас не осталось возможностей обработать фото!")
        return

    user.usages -= 1
    await user.save()

    await message.answer(f"Осталось {user.usages} использований.")

    if random.randint(0, 3) == 2:
        await message.answer(
            "Подписывайтесь на {partia}, {vera} и {anti}!\n"
            "Поддержите отечественную разработку {donate}!".format(
                partia=f'<a href="{escape("https://vk.com/partiarobotov")}">ПАРТИЮ</a>',
                vera=f'<a href="{escape("https://vk.com/the_biboran")}">Абдуловеру</a>',
                anti=f'<a href="{escape("https://vk.com/antibezpredel")}">Антибеспредел</a>',
                donate=f'<a href="{escape("http://donatepay.ru/d/vnukelkina")}">донатом</a>',
            )
        )

    await types.ChatActions.upload_photo()

    photo = BytesIO()
    await message.photo[-1].download(seek=True, destination=photo)
    photo_data = photo.read()
    photo.seek(0)

    async with ClientSession() as session:
        async with session.post(
            config.GAYBUSTER_API_URL, data={"photo": photo}, timeout=185
        ) as request:  # type: ClientResponse
            if request.status >= 400:
                await message.answer("Не удалось распознать фото. Попробуйте позже.")
                return
            result = await request.json()

    if result["count"] == 0:
        await message.answer("Лица на фото не найдены, попробуйте другой ракурс.")
        await User.filter(user_id=message.from_user.id).update(
            balance=F('balance') + 1
        )
        return

    prepared_photo = await dp.loop.run_in_executor(
        dp["process_pool_executor"], prepare_photo, photo_data, result["faces"]
    )

    await message.answer_photo(
        prepared_photo,
        caption=(
            "📕 - Скорее всего гей\n"
            "📙 - Недостаточная точность\n"
            "📗 - Скорее всего не гей\n\n"
            "Гейдетектор может плохо работать на женщинах, а так же на мужчинах младше 18 и старше 50"
        ),
    )

    file_code = str(uuid4())
    async with AIOFile(f"/detections/{file_code}.jpg", "wb") as photo_file:
        await photo_file.write(photo_data)

    async with AIOFile(f"/detections/{file_code}.json", "w") as description_file:
        await description_file.write(json.dumps(result))
Exemple #29
0
 async def test_save_f_expression(self):
     int_field = await IntFields.create(intnum=1)
     int_field.intnum = F("intnum") + 1
     await int_field.save(update_fields=["intnum"])
     n_int = await IntFields.get(pk=int_field.pk)
     self.assertEqual(n_int.intnum, 2)
 async def test_annotate_expression_filter(self):
     count = await IntFields.annotate(intnum=F("intnum") + 1
                                      ).filter(intnum__gt=30).count()
     self.assertEqual(count, 23)