File size: 7,534 Bytes
1f26706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# Ultroid - UserBot
# Copyright (C) 2021-2025 TeamUltroid
#
# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
# PLease read the GNU Affero General Public License in
# <https://www.github.com/TeamUltroid/Ultroid/blob/main/LICENSE/>.

"""
✘ Commands Available -

β€’ `{i}tw <tweet text>`
    Tweet the text.

β€’ `{i}twr <tweet id/link>`
    Get tweet details with reply/quote/comment count.

β€’ `{i}twuser <username>`
    Get user details of the Twitter account.

β€’ `{i}twl <tweet link>`
    Upload the tweet media to telegram.

"""

import os
from twikit import Client
from . import LOGS, eor, get_string, udB, ultroid_cmd

# Store client globally
twitter_client = None

# Get path to cookies file
COOKIES_FILE = "resources/auth/twitter_cookies.json"

async def get_client():
    global twitter_client
    if twitter_client:
        return twitter_client
        
    if not all(udB.get_key(key) for key in ["TWITTER_USERNAME", "TWITTER_EMAIL", "TWITTER_PASSWORD"]):
        raise Exception("Set TWITTER_USERNAME, TWITTER_EMAIL and TWITTER_PASSWORD in vars first!")
    
    # Create auth directory if it doesn't exist
    os.makedirs(os.path.dirname(COOKIES_FILE), exist_ok=True)
        
    client = Client()
    await client.login(
        auth_info_1=udB.get_key("TWITTER_USERNAME"),
        auth_info_2=udB.get_key("TWITTER_EMAIL"), 
        password=udB.get_key("TWITTER_PASSWORD"),
        cookies_file=COOKIES_FILE
    )
    twitter_client = client
    return client



@ultroid_cmd(pattern="tw( (.*)|$)")
async def tweet_cmd(event):
    """Post a tweet"""
    text = event.pattern_match.group(1).strip()
    if not text:
        return await event.eor("🚫 `Give some text to tweet!`")

    msg = await event.eor("πŸ•Š `Tweeting...`")
    try:
        client = await get_client()
        tweet = await client.create_tweet(text=text)
        await msg.edit(f"✨ **Successfully Posted!**\n\nπŸ”— https://x.com/{tweet.user.screen_name}/status/{tweet.id}")
    except Exception as e:
        await msg.edit(f"❌ **Error:**\n`{str(e)}`")


@ultroid_cmd(pattern="twdetail( (.*)|$)")
async def twitter_details(event):
    """Get tweet details"""
    match = event.pattern_match.group(1).strip()
    if not match:
        return await event.eor("🚫 `Give tweet ID/link to get details!`")

    msg = await event.eor("πŸ” `Getting tweet details...`")
    try:
        client = await get_client()
        from urllib.parse import urlparse
        parsed_url = urlparse(match)
        if parsed_url.hostname in ["twitter.com", "x.com"]:
            tweet_id = parsed_url.path.split("/")[-1].split("?")[0]
        else:
            tweet_id = match

        tweet = await client.get_tweet_by_id(tweet_id)
        text = "🐦 **Tweet Details**\n\n"
        text += f"πŸ“ **Content:** `{tweet.text}`\n\n"
        if hasattr(tweet, "metrics"):
            text += f"❀️ **Likes:** `{tweet.metrics.likes}`\n"
            text += f"πŸ”„ **Retweets:** `{tweet.metrics.retweets}`\n"
            text += f"πŸ’¬ **Replies:** `{tweet.metrics.replies}`\n"
            text += f"πŸ‘ **Views:** `{tweet.metrics.views}`\n"
        
        await msg.edit(text)
    except Exception as e:
        await msg.edit(f"❌ **Error:**\n`{str(e)}`")


@ultroid_cmd(pattern="twuser( (.*)|$)")
async def twitter_user(event):
    """Get user details"""
    match = event.pattern_match.group(1).strip()
    if not match:
        return await event.eor("🚫 `Give username to get details!`")

    msg = await event.eor("πŸ” `Getting user details...`")
    try:
        client = await get_client()
        user = await client.get_user_by_screen_name(match)
        text = "πŸ‘€ **Twitter User Details**\n\n"
        text += f"πŸ“› **Name:** `{user.name}`\n"
        text += f"πŸ”– **Username:** `@{user.screen_name}`\n"
        text += f"πŸ“ **Bio:** `{user.description}`\n\n"
        text += f"πŸ‘₯ **Followers:** `{user.followers_count}`\n"
        text += f"πŸ‘£ **Following:** `{user.following_count}`\n"
        text += f"🐦 **Total Tweets:** `{user.statuses_count}`\n"
        text += f"πŸ“ **Location:** `{user.location or 'Not Set'}`\n"
        text += f"βœ… **Verified:** `{user.verified}`\n"
        
        if user.profile_image_url:
            image_url = user.profile_image_url.replace("_normal.", ".")
            await event.client.send_file(
                event.chat_id,
                file=image_url,
                caption=text,
                force_document=False
            )
            await msg.delete()
        else:
            await msg.edit(text)
            
    except Exception as e:
        await msg.edit(f"❌ **Error:**\n`{str(e)}`")


@ultroid_cmd(pattern="twl( (.*)|$)")
async def twitter_media(event):
    """Download tweet media"""
    match = event.pattern_match.group(1).strip()
    if not match:
        return await event.eor("🚫 `Give tweet link to download media!`")

    msg = await event.eor("πŸ“₯ `Downloading media...`")
    try:
        client = await get_client()
        if "twitter.com" in match or "x.com" in match:
            tweet_id = match.split("/")[-1].split("?")[0]
        else:
            tweet_id = match

        tweet = await client.get_tweet_by_id(tweet_id)
        
        if not hasattr(tweet, "media"):
            return await msg.edit("πŸ˜• `No media found in tweet!`")

        # Prepare caption with tweet text
        caption = f"🐦 **Tweet by @{tweet.user.screen_name}**\n\n"
        caption += f"{tweet.text}\n\n"
        if hasattr(tweet, "metrics"):
            caption += f"❀️ `{tweet.metrics.likes}` πŸ”„ `{tweet.metrics.retweets}` πŸ’¬ `{tweet.metrics.replies}`"

        media_count = 0
        for media in tweet.media:
            if media.type == "photo":
                await event.client.send_file(
                    event.chat_id, 
                    media.url,
                    caption=caption if media_count == 0 else None  # Only add caption to first media
                )
                media_count += 1
            elif media.type == "video":
                if hasattr(media, "video_info") and isinstance(media.video_info, dict):
                    variants = media.video_info.get("variants", [])
                    mp4_variants = [
                        v for v in variants 
                        if v.get("content_type") == "video/mp4" and "bitrate" in v
                    ]
                    if mp4_variants:
                        best_video = max(mp4_variants, key=lambda x: x["bitrate"])
                        video_caption = caption if media_count == 0 else ""  # Only add tweet text to first media
                        if video_caption:
                            video_caption += f"\nπŸŽ₯ Video Quality: {best_video['bitrate']/1000:.0f}kbps"
                        else:
                            video_caption = f"πŸŽ₯ Video Quality: {best_video['bitrate']/1000:.0f}kbps"
                            
                        await event.client.send_file(
                            event.chat_id,
                            best_video["url"],
                            caption=video_caption
                        )
                        media_count += 1

        if media_count > 0:
            await msg.edit(f"βœ… Successfully downloaded {media_count} media items!")
            await msg.delete()
        else:
            await msg.edit("πŸ˜• `No media could be downloaded!`")
    except Exception as e:
        await msg.edit(f"❌ **Error:**\n`{str(e)}`")