I'm trying to get the invite link of a public channel and a public group.
I tried using the ExportChatInviteRequest function but it raises a ChatAdminRequiredError.
The thing I don't understand is why can I see and get the invite link of a public channel \ group with the telegram app but can't get it with telethon?
I use version 1.26.1:
from telethon.tl.functions.messages import ExportChatInviteRequest
async def main():
chat = await client.get_entity('https://t.me/bestmemes')
invite = await client(ExportChatInviteRequest(chat))
print(invite)
raises:
telethon.errors.rpcerrorlist.ChatAdminRequiredError: Chat admin privileges are required to do that in the specified chat (for example, to send a message in a channel which is not yours), or invalid permissions used for the channel or group (caused by ExportChatInviteRequest)
can someone help me, please?
I can see the invite of the given channel via the telegram app:
I did this:
Create a private chat with a bot or a friend
Retrieve api_id and api_hash from https://my.telegram.org/auth
Login to your telegram account using your phone number
Click "API Development tools"
Fill in your application details
Click on "Create application" at the end
Copy App api_id and App api_hash
from telethon import TelegramClient
from telethon.tl.functions.messages import ExportChatInviteRequest
session = 'Test' # The first-part name of a sqlite3 database - "Test.session"
# Contains user name and password to your Telegram account
# App ID and hash key to identify your Telegram App
api_id = 12345 # Use your own api_id
api_hash = '1234567890ABCDEFGHIJKLMNOPQRSTUV' # Use your own api_hash
# Create a connection to your telegram account using this app
# You will be asksed phone number, password, which will be stored into
# "Test.session" sqlite3 database
client = TelegramClient(session, api_id, api_hash)
async def main():
# Send a hello message to yourself
await client.send_message('me', 'Hello!')
# Send a hello message to a private chat group
await client.send_message('https://t.me/+xxxxxx', 'Hello!')
# Get a specific chat via its primary link
group = await client.get_entity('https://t.me/+xxxxxx')
# Create additional link
invite = await client(ExportChatInviteRequest(group))
print(invite.link) # Print secondary link
with client:
client.loop.run_until_complete(main())
The ExportChatInviteRequest method you are trying to use creates a private chat link. Obviously you can't do this if you're not an administrator
Here is a small code example that gets links to all open chats
async def get_chat_links():
dump = {}
# get all dialogs
for dialog in await client.get_dialogs():
chat = dialog.entity
# if the dialog does not have a title attribute, then it is not a group
if hasattr(chat, 'username') and hasattr(chat, 'title'):
dump[chat.title] = f'https://t.me/{chat.username}'
# for example, let's save everything to a file
with open('dump.json', 'w', encoding='utf-8') as file:
json.dump(dump, file, indent=4)
with client:
client.loop.run_until_complete(get_chat_links())
I would like to add some explanation about hasattr(chat, 'username'). For some chats you will have https://t.me/None. These are just the same closed chats that do not have an open link to join. But the ExportChatInviteRequest function will not work for these chats either, because it CREATES a link, and does not receive it. And if you are not an administrator in this chat you will get an error
Related
Good evening.
I hope that you are well.
I have posted an excerpt below of some Telegram bot code which auto forwards any messages it receives to another channel which has the bot added :-
api_key = ""
bot = telebot.TeleBot(api_key)
chat_id = "1234"
#bot.message_handler(func=lambda m: True)
def handle_posts(m: telebot.types.Message):
message_from = m.from_user.id
if message_from == 123456 or message_from == 654321:
print("You are an authorized user")
bot.forward_message(chat_id, m.chat.id, m.message_id)
else:
print("You are not an authorized user")
This code works fine for any text based messages that are sent to the bot (which includes standard formatting such as Bold, Italic, Underline, Emojis, Hyperlinks etc.) however if I attempt to attach an image to a message and then send it, the message is not forwarded on at all.
Does anyone have any idea how I can handle image based messages so that they forward successfully please?
Does it need another function that deals with a different telebot.types method perhaps?
Many thanks in advance
Jimmy
I have a bot that does something like this, but I only need to handle text and photos separately. I hope this code snipped helps!
# imports
from logging import Filter
from telegram import Update
from telegram.ext import *
import telegram
from dotenv import load_dotenv
import os
# get the telegram bot api_key from environment file
load_dotenv()
API_KEY = os.getenv('API_KEY')
# you will need the groub_b_id saved as a global variable or
# in some other document
group_b_id = 1234567890
# create the bot, updater, and dispatcher
bot = telegram.Bot(token=API_KEY)
updater = Updater(API_KEY, use_context=True)
dp = updater.dispatcher
def get_chat_id(update: Update, context: CallbackContext):
# gets the chat_id of the current chat
global bot
chat_id = update.effective_chat.id
bot.send_message(chat_id, "This chat's id is: " + str(chat_id))
def auto_forward(update: Update, context: CallbackContext):
# automatically forwards messages from this chat to
# chat_b
global bot, group_b_id
chat_id = update.effective_chat.id
username = update.effective_message.from_user.name
chat_title = update.effective_message.chat.title
msg_txt = update.effective_message.text
bot.send_message(
group_b_id,
text=f"'{msg_txt}'\nwas just sent in chat {chat_title} by {username}"
)
def auto_forward_image(update: Update, context: CallbackContext):
# get variables
global bot, group_b_id
chat_id = update.effective_chat.id
username = update.effective_message.from_user.name
chat_title = update.effective_message.chat.title
# get the third best quality photo
photos = len(update.message.photo)
img_index = max(photos-3, 0) # change -3 to -2 to get second best etc
img = update.message.photo[img_index]
# send message to GroupB the group that you want the stuff forwarded to
bot.send_message(group_b_id, str(username) + " just sent me an image from the `" + str(chat_title) + "` chat:")
bot.send_photo(group_b_id, img)
# sets up the handlers
dp.add_handler(CommandHandler('get_chat_id', get_chat_id))
dp.add_handler(MessageHandler(Filters.text, auto_forward))
dp.add_handler(MessageHandler(Filters.photo, auto_forward_image))
# Start the Bot
updater.start_polling()
updater.idle()
just make sure that you add the bot to both chats as an admin or this will not work since the bot needs admin priveleges to respond to all messages not just commands.
I want to use telethon to send messages to my own private channel, and receive mobile push notifications when the python script posts a message. With the below code I'm able to send the messages, but I do not receive any mobile push notifications. I've turned on all notification settings in the mobile app. I have been googling around for 'telethon push notifications', without any luck.
from telethon import TelegramClient
api_id = 'api_id'
api_hash = 'api_hash'
username = 'username'
channel_invite_link = 'channel invite link'
async def func():
entity = await client.get_entity(channel_invite_link)
await client.send_message(entity=entity, message="Hi")
with TelegramClient(username, api_id, api_hash) as client:
client.loop.run_until_complete(func())
Just use the silent argument, i.e.:
await client.send_message(entity=entity, message="Hi", silent=False)
I'm new to python and discord.py so sorry for any confusion. So I'm trying to make a modmail system for my bot however from my understanding there doesn't seem to be a way to get the server id from a dm or like there is, but if the bot is in multiple servers how do I figure out what server to send the message to? My idea was to check the message sent and see if the user sent the id of the server however I don't think I did it very well.
Here's what I currently did and it seems to work fine however just from the looks I know it can't be right.
#commands.Cog.listener()
async def on_message(self,message):
if not message.author.bot:
if isinstance(message.channel,DMChannel):
message_list = message.content.split()
server_id_sent = message_list[0]
for guild in self.client.guilds:
if str(guild.id) == server_id_sent:
message_list.remove(server_id_sent) #I thought by doing this I could remove the id from the message
guild = self.client.get_guild(int(server_id_sent))
print(guild)
modmail_channel = discord.utils.get(guild.channels, name="modmail")
modmail_channel_id = modmail_channel.id
channel = self.client.get_channel(modmail_channel_id)
await channel.send("TEST")
else:
await message.channel.send("Please provide the ID of the server")
By the way, first time using stackoverflow so hopefully I followed the format correctly.
Here's how I would do it:
We're going to set a command for when a user wants to send something to the specified server.
Getting the server name/ID won't actually be useful, as the bot won't know where to send that message. Instead, we will need a channel ID. To make this more user friendly, we're going to set a certain server name with it's channel id (let's just say it could be a log or ticket channel for the bot for these kind of messages)
I set mine like this:
Server: myServer
Server's channel ID: 1234567
Once we got the server name, we will send a message to the corresponding channel ID and send a message to the user that the request has been successfully recieved and made.
#client.event
async def on_message(message):
if message.content.startswith("?request"):
try:
server_name = message.content.split(' ')[1] #this gets the server name the user specified and saves it in a variable
except:
await message.channel.send("Invalid Usage! Syntax: ?request <serverID>")
return
if server_name == "myServer":
channel_id = 1234567
else:
await message.channel.send(f"The server `{server_name}` is not a valid server.")
return
get_channel = client.get_channel(channel_id)
await get_channel.send("Hello!")
#finally we're going to notify the user that his request has been successfully recieved
await message.channel.send(f"Message successfully sent to `{server_name}`!")
I am aware that
if server_name == "myServer":
channel_id = 1234567
is not really an elegant solution. If you want to store multiple servers with their respective logs channels ID's you could just store them in a dict or in a json file. Then access them in this way.
Json file example:
{
"myServer": "1234567",
"mySecondServer": 0987675
}
import json
json_file = open('servers.json').read()
servers = json.loads(json_file)
try:
get_channel_from_server = servers[server_name]
except:
await message.channel.send(f"The server `{server_name}` is not a valid server.")
I am subscribed to a private telegram Channel/chat where I am not admin and the username is not public.
I can get the channel id from the url in the form https://web.telegram.org/#/im?p=c1234567890_12345678901234567890
And can read all the messages in my telegram and via my web browser.
The channel outputs data (messages) that I want to grab and format and ultimately automatically append to a csv file or such like via a bot or an app on my mac.
Is it possible to do this?
I am currently trying to do this in Python using the Telethon package.
I have been trying to access or address the channel by ID but get errors like
No user has "c1234567890" as username
Or
No user has "-1001234567890" as username
I am trying to use the telethon client.getmessages() method but looks like it will only accept a username and not a chat or channel ID.
Any help/guidance or pointing in the right direction appreciated - I think my main issue is resolving the channel ID to a username or finding classes/methods where I can get the messages by channel ID.
yes, you can used channel ID for search. use it as a int not as a String
this code will help you to understand.
from telethon import TelegramClient
# Remember to use your own values from my.telegram.org!
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
client = TelegramClient('anon', api_id, api_hash)
async def main():
# You can print the message history of any chat:
# chat id is -1001209767229
async for message in client.iter_messages(-1001209767229):
print(message.sender.username, message.text)
with client:
client.loop.run_until_complete(main())
I'm trying to make my python script send messages to my private channel but I get this error.
telethon.errors.rpcerrorlist.ChatWriteForbiddenError: You can't write in this chat (caused by SendMessageRequest)
I'm only admin in that channel and here is code what I use for sending messages, when I try to send message to myself it works fine..
from telethon import TelegramClient
from telethon.errors import SessionPasswordNeededError
api_id = 'my api id'
api_hash = 'my api hash'
phone = 'my number'
username = 'my username'
# Create the client and connect
client = TelegramClient(username, api_id, api_hash)
client.start()
print("Client Created")
# Ensure you're authorized
if not client.is_user_authorized():
client.send_code_request(phone)
try:
client.sign_in(phone, input('Enter the code: '))
except SessionPasswordNeededError:
client.sign_in(password=input('Password: '))
async def send_mess(message):
await client.send_message(entity='my channel name', message=message)
while True:
some other code
if last_message != new_message:
with client:
client.loop.run_until_complete(send_mess(message=new_message))
last_message = new_message
Do I need to change something to have admin rights on my script or where is the problem? I'll be glad for every answer. Gimme some good sample code guys :D this is really big problem for me now.
At first test that you can send message to another channel or user. if you can't you must share all the code.
then make sure that account you are using at this case is admin in the channel. it's impossible you getting this error if the account is admin.
also check admin rights and make sure post message is enable.
between, use channel username or channel numeric id instead 'my channel name'. channel numeric id starts with -100 like -1001212229355. you better to use numeric id. to find this just forward one of your channel messages to https://t.me/userinfobot.
await client.send_message(entity='my channel name', message=message)