Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add attribute "correct" for PollOption #788

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dashezup
Copy link

I found that I can't find which answer is correct in a quiz poll. so I created this PR to add the "correct" option for PollOption. This is an essential feature that I need for one of my project.

I've made the "correct" option optional.

Example result of result of PollOption of a quiz poll

{                                                                                                                                                                                     "_": "types.PollAnswerVoters",
    "option": "b'2'",             
    "voters": 2,              
    "chosen": false,          
    "correct": false                                                                 
}

I've tested it locally by install it from git repo. seems to work fine (when I print the message/poll, it shows "correct" in poll option when it's a quiz poll, or no "correct" attribute when the poll type is not quiz)

@dashezup dashezup changed the title feat: add attribute correct to PollOption feat: add attribute "correct" to PollOption Nov 25, 2021
@dashezup dashezup changed the title feat: add attribute "correct" to PollOption feat: add attribute "correct" for PollOption Nov 25, 2021
@dashezup
Copy link
Author

dashezup commented Nov 27, 2021

_parse_update() may also need to be edited

@kinshusharma0412
Copy link

Can we add explanation option also
Means (view explanation + send explanation both option)
Correct option work successful.
Thankyou for your hard work

@dashezup
Copy link
Author

dashezup commented Jan 5, 2022

Can we add explanation option also
Means (view explanation + send explanation both option)

@kinshusharma0412 I monkeypatched it to include correct and solution option (for view only) for my own use, It should also easy for you to do the same.

solution=media_poll.results.solution for Poll

there is media_poll.results.solution_entities which I don't know how to deal with, just adding solution_entities=media_poll.results.solution_entities sometimes can cause errors. so I'm not going to do it in this PR.

@kinshusharma0412
Copy link

Yes explanation added as you say

Thanks brother

If possible to add explanation in send_poll class.
Please add it.

@kinshusharma0412
Copy link

I do not know how to attach file so code down blow

def __init__(
    self,
    *,
    client: "pyrogram.Client" = None,
    id: str,
    question: str,
    options: List["types.PollOption"],
    total_voter_count: int,
    is_closed: bool,
    is_anonymous: bool = None,
    type: str = None,
    allows_multiple_answers: bool = None,
    # correct_option_id: int,
    chosen_option: int = None,
    **exp: str**
):
    super().__init__(client)

    self.id = id
    self.question = question
    self.options = options
    self.total_voter_count = total_voter_count
    self.is_closed = is_closed
    self.is_anonymous = is_anonymous
    self.type = type
    self.allows_multiple_answers = allows_multiple_answers
    # self.correct_option_id = correct_option_id
    self.chosen_option = chosen_option
    **self.exp = exp**

@staticmethod
def _parse(client, media_poll: Union["raw.types.MessageMediaPoll", "raw.types.UpdateMessagePoll"]) -> "Poll":
    
    poll = media_poll.poll  # type: raw.types.Poll
    results = media_poll.results.results
    **if media_poll.results.solution:
        exp = media_poll.results.solution
    else:
        exp = None**
    chosen_option = None
    options = []

    for i, answer in enumerate(poll.answers):
        voter_count = 0
        correct = None

        if results:
            result = results[i]
            voter_count = result.voters
            correct = result.correct

            if result.chosen:
                chosen_option = i

        options.append(
            types.PollOption(
                text=answer.text,
                voter_count=voter_count,
                correct=correct,
                data=answer.option,
                client=client
            )
        )

    return Poll(
        id=str(poll.id),
        question=poll.question,
        options=options,
        total_voter_count=media_poll.results.total_voters,
        is_closed=poll.closed,
        is_anonymous=not poll.public_voters,
        type="quiz" if poll.quiz else "regular",
        allows_multiple_answers=poll.multiple_choice,
        chosen_option=chosen_option,
        **exp=exp,**
        client=client
    )

@staticmethod
def _parse_update(client, update: "raw.types.UpdateMessagePoll"):
    if update.poll is not None:
        return Poll._parse(client, update)

    results = update.results.results
    
    chosen_option = None
    options = []

    for i, result in enumerate(results):
        if result.chosen:
            chosen_option = i

        options.append(
            types.PollOption(
                text="",
                voter_count=result.voters,
                data=result.option,
                client=client
            )
        )

    return Poll(
        id=str(update.poll_id),
        question="",
        options=options,
        total_voter_count=update.results.total_voters,
        is_closed=False,
        chosen_option=chosen_option,
        results=results,
        client=client
    )

@kinshusharma0412
Copy link

Here is results

Print(message)👇👇👇

{
"": "Message",
"message_id": 2265,
"from_user": {
"
": "User",
"id": 711296045,
"is_self": false,
"is_contact": false,
"is_mutual_contact": false,
"is_deleted": false,
"is_bot": false,
"is_verified": false,
"is_restricted": false,
"is_scam": false,
"is_fake": false,
"is_support": false,
"first_name": "ᡕᠵ᠊ᡃ່࡚ࠢ࠘ ⸝່ࠡࠣ᠊߯᠆ࠣ࠘ᡁࠣ࠘᠊᠊ࠢ࠘𐡏 ꠋꠋꠋꠋ
"last_name": "SHARMA ✿◉●┅┄",
"status": "recently",
"username": "Kinbin247",
"dc_id": 5,
"photo": {
"": "ChatPhoto",
"small_file_id": "AQADBQAD9KcxGy2EZSoAEAIAAy2EZSoABFOH-dBN6GbXAAQeBA",
"small_photo_unique_id": "AgAD9KcxGy2EZSo",
"big_file_id": "AQADBQAD9KcxGy2EZSoAEAMAAy2EZSoABFOH-dBN6GbXAAQeBA",
"big_photo_unique_id": "AgAD9KcxGy2EZSo"
}
},
"date": "2022-01-05 13:50:36",
"chat": {
"
": "Chat",
"id": 711296045,
"type": "private",
"is_verified": false,
"is_restricted": false,
"is_scam": false,
"is_fake": false,
"is_support": false,
"username": "Kinbin247",
"first_name": "ᡕᠵ᠊ᡃ່࡚ࠢ࠘ ⸝່ࠡࠣ᠊߯᠆ࠣ࠘ᡁࠣ࠘᠊᠊ࠢ࠘𐡏 ꠋꠋꠋꠋ
"last_name": "SHARMA ✿◉●┅┄",
"photo": {
"": "ChatPhoto",
"small_file_id": "AQADBQAD9KcxGy2EZSoAEAIAAy2EZSoABFOH-dBN6GbXAAQeBA",
"small_photo_unique_id": "AgAD9KcxGy2EZSo",
"big_file_id": "AQADBQAD9KcxGy2EZSoAEAMAAy2EZSoABFOH-dBN6GbXAAQeBA",
"big_photo_unique_id": "AgAD9KcxGy2EZSo"
},
"dc_id": 5
},
"forward_from": {
"
": "User",
"id": 1355592440,
"is_self": false,
"is_contact": false,
"is_mutual_contact": false,
"is_deleted": false,
"is_bot": true,
"is_verified": false,
"is_restricted": false,
"is_scam": false,
"is_fake": false,
"is_support": false,
"first_name": "Mohit Sharma",
"username": "KINBIN247_bot",
"dc_id": 5,
"photo": {
"": "ChatPhoto",
"small_file_id": "AQADBQAD-qkxG00b0FQAEAIAA_iyzFAABEMzQguhRd6YAAQeBA",
"small_photo_unique_id": "AgAD-qkxG00b0FQ",
"big_file_id": "AQADBQAD-qkxG00b0FQAEAMAA_iyzFAABEMzQguhRd6YAAQeBA",
"big_photo_unique_id": "AgAD-qkxG00b0FQ"
}
},
"forward_date": "2022-01-05 13:11:01",
"mentioned": false,
"scheduled": false,
"from_scheduled": false,
"media": true,
"poll": {
"
": "Poll",
"id": "6244574825646391343",
"question": "T",
"options": [
{
"": "PollOption",
"text": "(A) Q",
"voter_count": 0,
"correct": true,
"data": "b'0'"
},
{
"
": "PollOption",
"text": "(B) Q",
"voter_count": 0,
"correct": false,
"data": "b'1'"
},
{
"": "PollOption",
"text": "(C) Q",
"voter_count": 0,
"correct": false,
"data": "b'2'"
},
{
"
": "PollOption",
"text": "(D) Q",
"voter_count": 0,
"correct": false,
"data": "b'3'"
}
],
"total_voter_count": 0,
"is_closed": true,
"is_anonymous": false,
"type": "quiz",
"allows_multiple_answers": false,
"exp": "Exp\nExp"
},
"outgoing": false
}

@kinshusharma0412
Copy link

kinshusharma0412 commented Jan 5, 2022

After some time

This error comes

init() got an unexpected keyword argument 'results'
Traceback (most recent call last):
File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.9/site-packages/pyrogram/dispatcher.py", line 191, in handler_worker
await parser(update, users, chats)
File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.9/site-packages/pyrogram/dispatcher.py", line 101, in poll_parser
return pyrogram.types.Poll._parse_update(self.client, update), PollHandler
File "/data/user/0/ru.iiec.pydroid3/files/aarch64-linux-android/lib/python3.9/site-packages/pyrogram/types/messages_and_media/poll.py", line 161, in _parse_update
return Poll(
TypeError: init() got an unexpected keyword argument 'results'

But
after this error
Function didn't stop
Script run

@kinshusharma0412
Copy link

No error for this code 👇👇👇

@kinshusharma0412
Copy link

kinshusharma0412 commented Jan 6, 2022

Pyrogram - Telegram MTProto API Client Library for Python

Copyright (C) 2017-2021 Dan https://github.com/delivrance

This file is part of Pyrogram.

Pyrogram is free software: you can redistribute it and/or modify

it under the terms of the GNU Lesser General Public License as published

by the Free Software Foundation, either version 3 of the License, or

(at your option) any later version.

Pyrogram is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License

along with Pyrogram. If not, see http://www.gnu.org/licenses/.

from typing import List, Union

import pyrogram
from pyrogram import raw
from pyrogram import types
from ..object import Object
from ..update import Update

class Poll(Object, Update):
"""A Poll.

Parameters:
    id (``str``):
        Unique poll identifier.

    question (``str``):
        Poll question, 1-255 characters.

    options (List of :obj:`~pyrogram.types.PollOption`):
        List of poll options.

    total_voter_count (``int``):
        Total number of users that voted in the poll.

    is_closed (``bool``):
        True, if the poll is closed.

    is_anonymous (``bool``, *optional*):
        True, if the poll is anonymous

    type (``str``, *optional*):
        Poll type, currently can be "regular" or "quiz".

    allows_multiple_answers (``bool``, *optional*):
        True, if the poll allows multiple answers.

    chosen_option (``int``, *optional*):
        Index of your chosen option (0-9), None in case you haven't voted yet.
"""

def __init__(
    self,
    *,
    client: "pyrogram.Client" = None,
    id: str,
    question: str,
    options: List["types.PollOption"],
    total_voter_count: int,
    is_closed: bool,
    is_anonymous: bool = None,
    type: str = None,
    allows_multiple_answers: bool = None,
    # correct_option_id: int,
    chosen_option: int = None,
    #exp: str = None
):
    super().__init__(client)

    self.id = id
    self.question = question
    self.options = options
    self.total_voter_count = total_voter_count
    self.is_closed = is_closed
    self.is_anonymous = is_anonymous
    self.type = type
    self.allows_multiple_answers = allows_multiple_answers
    # self.correct_option_id = correct_option_id
    self.chosen_option = chosen_option
    #self.exp = exp
    

@staticmethod
def _parse(client, media_poll: Union["raw.types.MessageMediaPoll", "raw.types.UpdateMessagePoll"]) -> "Poll":
    
    poll = media_poll.poll  # type: raw.types.Poll
    results = media_poll.results.results
    chosen_option = None
    options = []

    for i, answer in enumerate(poll.answers):
        voter_count = 0
        correct = None

        if results:
            result = results[i]
            voter_count = result.voters
            correct = result.correct

            if result.chosen:
                chosen_option = i

        options.append(
            types.PollOption(
                text=answer.text,
                voter_count=voter_count,
                correct=correct,
                exp=media_poll.results.solution,
                data=answer.option,
                client=client
            )
        )

    return Poll(
        id=str(poll.id),
        question=poll.question,
        options=options,
        total_voter_count=media_poll.results.total_voters,
        is_closed=poll.closed,
        is_anonymous=not poll.public_voters,
        type="quiz" if poll.quiz else "regular",
        allows_multiple_answers=poll.multiple_choice,
        chosen_option=chosen_option,
        #exp=exp,
        client=client
    )

@staticmethod
def _parse_update(client, update: "raw.types.UpdateMessagePoll"):
    if update.poll is not None:
        return Poll._parse(client, update)
    
    results = update.results.results
    #print("update==="+str(update))
    chosen_option = None
    options = []

    for i, result in enumerate(results):
        if result.chosen:
            chosen_option = i

        options.append(
            types.PollOption(
                text="",
                voter_count=result.voters,
                data=result.option,
                exp=None,
                client=client
            )
        )
        
    return Poll(
        id=str(update.poll_id),
        question="",
        options=options,
        total_voter_count=update.results.total_voters,
        is_closed=False,
        chosen_option=chosen_option,
        
        #results=results,
        client=client
    )

@kinshusharma0412
Copy link

Pyrogram - Telegram MTProto API Client Library for Python

Copyright (C) 2017-2021 Dan https://github.com/delivrance

This file is part of Pyrogram.

Pyrogram is free software: you can redistribute it and/or modify

it under the terms of the GNU Lesser General Public License as published

by the Free Software Foundation, either version 3 of the License, or

(at your option) any later version.

Pyrogram is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License

along with Pyrogram. If not, see http://www.gnu.org/licenses/.

import pyrogram
from ..object import Object

class PollOption(Object):
"""Contains information about one answer option in a poll.

Parameters:
    text (``str``):
        Option text, 1-100 characters.

    voter_count (``int``):
        Number of users that voted for this option.
        Equals to 0 until you vote.

    data (``bytes``):
        The data this poll option is holding.

    correct (``bool``, *optional*):
        the option is the correct answer
        
    exp (``str``):
        Option text, 1-100 characters.
        
        
"""

def __init__(
    self,
    *,
    client: "pyrogram.Client" = None,
    text: str,
    voter_count: int,
    data: bytes,
    correct: bool = None,
    exp: str
):
    super().__init__(client)

    self.text = text
    self.voter_count = voter_count
    self.correct = correct
    self.exp = exp
    self.data = data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants