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

Create input_user.rs #208

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

Conversation

tingfeng-key
Copy link
Contributor

No description provided.

Copy link
Owner

@Lonami Lonami left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to expose Input types to the user of the library. The PackedChat abstraction already covers this usecase.

@Lonami Lonami closed this Nov 18, 2023
@tingfeng-key
Copy link
Contributor Author

tingfeng-key commented Nov 19, 2023

pub enum MessageEntity {
    Unknown(crate::types::MessageEntityUnknown),
    Mention(crate::types::MessageEntityMention),
    Hashtag(crate::types::MessageEntityHashtag),
    BotCommand(crate::types::MessageEntityBotCommand),
    Url(crate::types::MessageEntityUrl),
    Email(crate::types::MessageEntityEmail),
    Bold(crate::types::MessageEntityBold),
    Italic(crate::types::MessageEntityItalic),
    Code(crate::types::MessageEntityCode),
    Pre(crate::types::MessageEntityPre),
    TextUrl(crate::types::MessageEntityTextUrl),
    MentionName(crate::types::MessageEntityMentionName),
    InputMessageEntityMentionName(crate::types::InputMessageEntityMentionName),
    Phone(crate::types::MessageEntityPhone),
    Cashtag(crate::types::MessageEntityCashtag),
    Underline(crate::types::MessageEntityUnderline),
    Strike(crate::types::MessageEntityStrike),
    BankCard(crate::types::MessageEntityBankCard),
    Spoiler(crate::types::MessageEntitySpoiler),
    CustomEmoji(crate::types::MessageEntityCustomEmoji),
    Blockquote(crate::types::MessageEntityBlockquote),
}

pub struct InputMessageEntityMentionName {
    pub offset: i32,
    pub length: i32,
    pub user_id: crate::enums::InputUser,
}

If input_user is not open, how should the user_id field of the InputMessageEntityMentionName structure be used? Is there a better way

I am now implementing conversion for MessageEntity to make it more convenient for library users.

I looked at PackedChat, but I didn’t see the conversion from tl::enums::InputUser, that is, tl::enums::InputUser to PackedChat, and I saw that tl::enums::InputUser is used in many places in the library. I think Adding input_user.rs works, and so does input_peer.rs. If you have a better idea, I will try it.

@tingfeng-key
Copy link
Contributor Author

The content of the entity.rs file I have implemented now is roughly as follows, which can facilitate the message to obtain entity information:

#[derive(Debug)]
pub enum EntityType {
    Unknown,
    Mention,
    Hashtag,
    BotCommand,
    Url,
    Email,
    Bold,
    Italic,
    Code,
    Pre(String),
    TextUrl(String),
    MentionName(i64),
    InputMessageEntityMentionName(types::input_user::InputUser),
    Phone,
    Cashtag,
    Underline,
    Strike,
    BankCard,
    Spoiler,
    CustomEmoji(i64),
    Blockquote,
}

impl From<tl::enums::MessageEntity> for EntityType {
    fn from(entity: tl::enums::MessageEntity) -> Self {
        use tl::enums::MessageEntity as TlMessageEntity;
        match entity {
            TlMessageEntity::Unknown(_) => Self::Unknown,
            TlMessageEntity::Mention(_) => Self::Mention,
            TlMessageEntity::Hashtag(_) => Self::Hashtag,
            TlMessageEntity::BotCommand(_) => Self::BotCommand,
            TlMessageEntity::Url(_) => Self::Url,
            TlMessageEntity::Email(_) => Self::Email,
            TlMessageEntity::Bold(_) => Self::Bold,
            TlMessageEntity::Italic(_) => Self::Italic,
            TlMessageEntity::Code(_) => Self::Code,
            TlMessageEntity::Pre(pre) => Self::Pre(pre.language.clone()),
            TlMessageEntity::TextUrl(text_url) => Self::TextUrl(text_url.url.clone()),
            TlMessageEntity::MentionName(user) => Self::MentionName(user.user_id),
            TlMessageEntity::InputMessageEntityMentionName(user) => {
                Self::InputMessageEntityMentionName(types::input_user::InputUser::_from_raw(
                    user.user_id.clone(),
                ))
            }
            TlMessageEntity::Phone(_) => Self::Phone,
            TlMessageEntity::Cashtag(_) => Self::Cashtag,
            TlMessageEntity::Underline(_) => Self::Underline,
            TlMessageEntity::Strike(_) => Self::Strike,
            TlMessageEntity::BankCard(_) => Self::BankCard,
            TlMessageEntity::Spoiler(_) => Self::Spoiler,
            TlMessageEntity::CustomEmoji(emoji) => Self::CustomEmoji(emoji.document_id),
            TlMessageEntity::Blockquote(_) => Self::Blockquote,
        }
    }
}

#[derive(Debug)]
pub struct Entity {
    r#type: EntityType,
    text: String,
}

impl Entity {
    pub(crate) fn _from_message(
        text: &str,
        message_entities: Option<Vec<tl::enums::MessageEntity>>,
    ) -> Vec<Self> {
        let mut entities = vec![];
        if let Some(original_entities) = message_entities {
            for msg_entity in original_entities {
                entities.push(Self::_tranform(text, &msg_entity));
            }
        }
        entities
    }

    fn _tranform(message_text: &str, entity: &tl::enums::MessageEntity) -> Self {
        let text_u16 = message_text
            .encode_utf16()
            .skip(entity.offset() as usize)
            .take(entity.length() as usize)
            .collect::<Vec<u16>>();

        Self {
            r#type: entity.clone().into(),
            text: String::from_utf16(&text_u16).unwrap_or_default(),
        }
    }

    pub fn _type(&self) -> &EntityType {
        &self.r#type
    }
    pub fn text(&self) -> &str {
        &self.text
    }
}

@Lonami
Copy link
Owner

Lonami commented Nov 19, 2023

If input_user is not open, how should the user_id field of the InputMessageEntityMentionName structure be used? Is there a better way

Telegram's current syntax for inline mentions is using a link with the tg://user?id=... as the URL. In HTML, that would be <a href="tg://user?id=123">inline mention</a>.

We could instead support a different URL parameter, such as packed=, which could take the PackedChat::hex, as in <a href="tg://user?packed=12ab34cd">inline mention</a>. This could become Telegram's types::InputMessageEntityMentionName.

This way we don't need to expose entities to the user at all, but they're free to use HTML instead.

I don't think "raw offsets" are that useful. Sure, it might be a bit more powerful. But HTML can get you all of that in a more readable format.

I am now implementing conversion for MessageEntity to make it more convenient for library users.

Is it really more convenient than HTML? What is your usecase?

@Lonami
Copy link
Owner

Lonami commented Nov 19, 2023

I don't plan to merge this, but I'll keep it open for now so we can discuss it.

@Lonami Lonami reopened this Nov 19, 2023
@tingfeng-key
Copy link
Contributor Author

Thank you for your willingness to discuss it. My current scenario is to get the MessageEntity content more conveniently and humanely, such as getting the username and user_id in the entity. Currently I have not used the InputMessageEntityMentionName, but I am working on this content. Sometimes, I want to make it as complete as possible, so this question arises

@tingfeng-key
Copy link
Contributor Author

At present, when I deal with entities, I get the original data structure every time. Therefore, I wonder if this operation can be simplified. Otherwise, I need to use the tl_type library externally, that is, the code generated by the library. I want to avoid it as much as possible. Rely on raw data structures, but get more human-friendly data structures from client::types for ease of use

@Lonami
Copy link
Owner

Lonami commented Nov 19, 2023

Ah so your goal is a friendlier version of

pub fn fmt_entities(&self) -> Option<&Vec<tl::enums::MessageEntity>> {
, like Telethon v1's https://docs.telethon.dev/en/stable/modules/custom.html#telethon.tl.custom.message.Message.get_entities_text. Yeah, that's a fair ask. But in that case we should probably not show the user the InputUser, but a PackedChat.

@tingfeng-key
Copy link
Contributor Author

Yes, can I change the access attribute of input_user.rs to pub(crate) and add the conversion of Into<PackedChat> to achieve InputMessageEntityMentionName(PackedChat)? I thought about doing this, but I found tl::enums::InputUser's Empty and UserSelf suitable for processing in this way? Do you have a better method?

@Lonami
Copy link
Owner

Lonami commented Nov 20, 2023

Telegram should not return InputMessageEntityMentionName. That's only an Input parameter when sending requests. So maybe we should just panic if we try to convert from that.

@tingfeng-key
Copy link
Contributor Author

Then should I implement the MessageEntity structure? This makes me confused

@Lonami
Copy link
Owner

Lonami commented Nov 21, 2023

My current scenario is to get the MessageEntity content more conveniently and humanely

You said "get". I am assuming you fetched or received a message and want to access its formatting entities. This means InputMessageEntityMentionName will never occur and we do not need to handle it. Therefore, there is no need to have input users exposed.

InputMessageEntityMentionName would only be needed if grammers were to offer a way to send a message with some entities. But it doesn't, because markdown and HTML formatting covers that usecase.

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

Successfully merging this pull request may close these issues.

2 participants