Transfer Telegram channel ownership using pyrogram library - python

How to transfer channel ownership?
I want to transfer ownership of a Telegram channel using pyrogram.
There is a promote_chat_member method but it does not have an owner input parameter. There is also a pyrogram.raw.functions.channels.EditCreator method but I don't understand how to use it.

Try this in order to use the pyrogram.raw.functions.channels.EditCreator method
NOTES:
This operation must be done with an user account. It's necessary that you pass your phone number to the Client. (This operations can't be performed by bots)
The user must be a member of the channel. The code will promote the
user to Admin.
Get new_owner_id and channel_id using IDBot in Telegram (#username_to_id_bot). You'll need to send the username of the new owner and the join link of the channel to the bot.
Set a 2FA password in your account at least 1 week before running the
code (it's an API requirement)
Requirements
pip install pyrogram
pip install nest-asyncio
CODE
from pyrogram import Client
from pyrogram.raw.functions.channels import EditCreator
from pyrogram.raw.functions.account import GetPassword
import nest_asyncio
nest_asyncio.apply()
app = Client("app_name_you_like",api_id="your_api_id",api_hash="your_api_hash",phone_number="your_phone_number")
channel_id = channel_id #int -> enter your channel_id here
user_id = new_owner_id #int -> enter your new_owner_id here
async def make_owner():
await app.start()
channel_data = await app.resolve_peer(channel_id)
user_data = await app.resolve_peer(user_id)
password = await app.invoke(GetPassword())
#Make user Admin
await app.promote_chat_member(channel_id, user_id)
#Make user Owner
await app.invoke(EditCreator(channel=channel_data,user_id=user_data,password=password))
await app.stop()
app.run(make_owner())
Extra Notes:
If you don't have your Telegram API Credentials you can get them in this link

Here's a sample code how you can do it
from pyrogram import Client
# Creating Pyrogram client
app = Client("my_account")
app.start()
# replace the below channel_username with Channel you want to transfer ownership of
channel = app.get_chat("channel_username")
# Get the ID of the user whom you want to transfer
new_owner_id = 00000 # Replace 00000 wit the id of new owner
# Get the current owner ID of the channel
current_owner_id = channel.owner_id
# Transfer Ownsership
app.edit_administrator(
chat_id=channel.id,
user_id=new_owner_id,
is_owner=True,
can_change_info=True,
can_invite_users=True,
can_delete_messages=True,
can_restrict_members=True,
can_pin_messages=True,
can_promote_members=True
)
# Revoke the old owner's admin permissions
app.edit_administrator(
chat_id=channel.id,
user_id=current_owner_id,
is_owner=False,
can_change_info=False,
can_invite_users=False,
can_delete_messages=False,
can_restrict_members=False,
can_pin_messages=False,
can_promote_members=False
)
# Logout
app.stop()

Related

Send message to user when he is online in Pyrogram

I am using Pyrogram to make userbot. I need to check if user is online and if he is online I will send him a message. I couldn't understand documentation.
from pyrogram import Client
app = Client(
"my_account",
api_id= 111111111,
api_hash='bbbbbbbbbbbbbbbbb'
)
chat_id = 777777777
with app:
peer = app.resolve_peer(chat_id)
if(is_user_online(chat_id)):
app.send_message(chat_id=chat_id, text='Hello!')
I tried to use pyrogram.types.User, but I didn't understand what I am doing.
To check if a user is online, you could use the get_users() method of the Client class that checks the status field of the returned User object.
from pyrogram import Client
app = Client(
"my_account",
api_id= 111111111,
api_hash='bbbbbbbbbbbbbbbbb'
)
chat_id = 777777777
with app:
user = app.get_users(chat_id)
if str(user.status) == "UserStatus.ONLINE"
app.send_message(chat_id=chat_id, text="Hello!")
The status field of the User object tells you when the user was online for the last time.

python telegrambot store chat id

I am wondering how I could store/read out a user chat ID to later send them messages.
Example would be, that the user is adding my telegram bot and sends him a message.
Later on in my program at some point, when a sepcific situation occurs, I want to send a message to the specific user.
For a simple example I have this code:
a=1
b=2
if a > b:
# at this point python should send a message to a user via telegram privat chat
else:
# send a different message
I know how to handle a response to a command sent by the user in the telegram chat, but not how to send a message to a user without receiving a command first. I think there fore I would need to have a way to store the users chat Id first to later refer to that Id when sending the message.
The point is I want to compile my program to .exe later on and send it to some friends and it should work for them as well.
It is very easy, just use a simple database.
MongoDB is the best choose in my opinion.
Create an account on it and follow this tutorial.
First get the user_id
userid1 = str(update.message.chat_id)
Then store it into the database
import pymongo
from pymongo import MongoClient
cluster = MongoClient("mongodb+srv://<user>:<password>#cluster0.uubct.mongodb.net/users?retryWrites=true&w=majority")
db = cluster["users"]
collection = db["users"]
results = collection.find({"_id": int(userid1)})
if results.count() == 0:
print("post")
post = {"_id": int(userid1)}
collection.insert_one(post)
else:
print("User already in the database!")
For getting it you need to use the find() method.
results = collection.find()
for result in results:
var1 = (result["_id"])
print(var1)
context.bot.send_message(chat_id=prova,
text = "Hi")
You can simply add the id in a list WHITOUT ANY THIRD PARTS PAKAGE
import telebot
TOKEN = ""
bot = telebot.TeleBot(TOKEN)
admin = # your chat id
users = []
#bot.message_handler(commands=['start'])
def start_message(msg):
bot.send_message(msg.chat.id, 'Welcome!')
if msg.chat.id not in users: # if the id isn't already in the users list
users.append(msg.chat.id)
#bot.message_handler(commands=['send_at_all']) # A way to use the list
def sendAtAll(msg):
if msg.chat.id == admin: # only if YOU start the command the message will be sent
for id in users: # for every user that has start the bot
bot.send_message(id, "I'm sending this message at all the users")
# If an user wants to stop the notifications...
#bot.message_handler(commands=['unsubscribe'])
def sendAtAll(msg):
del users[msg.chat.id]
bot.send_message(msg.chat.id, "If you want to receive the notification click /start")
# Every time you are going to restart the bot polling the content of the users list will be deleated so...
#bot.message_handler(commands=['save_user_list'])
def sendAtAll(msg):
if msg.chat.id == admin:
bot.send_message(admin, users)
# the list will be sent to your telegram chat, when you activate the bot you can add the list manually
bot.polling()
You can also create a class and save every chat id as an object
import telebot
from random import choice
TOKEN = ''
bot = telebot.TeleBot(TOKEN)
admin = # your chat id
users = []
class Userbot: # The class User is already in the pyTelegramBotAPI
def __init__(self, msg):
self.id = msg.chat.id
self.username = '#' + msg.from_user.username
def contestWinner(self):
text = f'Hi {self.username}, you have win!!!'
bot.send_message(self.id, text)
#bot.message_handler(commands=['start'])
def start(msg):
bot.send_message(msg.chat.id, 'Welcome!')
for el in users:
if msg.chat.id not in el.id:
users.append(Userbot(msg))
# you can't type 'if msg.chat.id not in users.id' because only the object inside the list can use the method id
#bot.message_handler(commands=['extract']) # another way to use the list
def extract(msg):
if msg.chat.id == admin:
winner = choice(users)
winner.contestWinner()
#bot.message_handler(commands=['unsubscribe'])
def sendAtAll(msg):
for el in users:
if msg.chat.id == el.id:
del users[el]
# only if the user inside the object is the same as the user that has sent the message the object will be deleated
bot.send_message(msg.chat.id, "If you want to receive the notification click /start")
#bot.message_handler(commands=['save_user_list'])
def sendAtAll(msg):
if msg.chat.id == admin:
bot.send_message(admin, users)
bot.polling()
Apologise for my terrible english

Send a local photo from inline mode in a telegram bot

I use Python telegram bot API for my bot.
I want to generate photos locally and send them as inline results but InlineQueryResultPhoto accepts only photo URLs.
Suppose my project structure looks like this:
main.py
photo.jpg
How do I send photo.jpg as an inline result?
Here is the code of main.py:
from uuid import uuid4
from telegram.ext import InlineQueryHandler, Updater
from telegram import InlineQueryResultPhoto
def handle_inline_request(update, context):
update.inline_query.answer([
InlineQueryResultPhoto(
id=uuid4(),
photo_url='', # WHAT DO I PUT HERE?
thumb_url='', # AND HERE?
)
])
updater = Updater('TELEGRAM_TOKEN', use_context=True)
updater.dispatcher.add_handler(InlineQueryHandler(handle_inline_request))
updater.start_polling()
updater.idle()
There is no direct answer because Telegram Bot API doesn't provide it.
But there are two workaounds: you can use upload a photo to telegram servers and then use InlineQueryResultCachedPhoto or you can upload to any image server and then use InlineQueryResultPhoto.
InlineQueryResultCachedPhoto
This first option requires you to previously upload the photo to telegram servers before creating the result list. Which options do you have? The bot can message you the photo, get that information and use what you need. Another option is creating a private channel where your bot can post the photos it will reuse. The only detail of this method is getting to know the channel_id (How to obtain the chat_id of a private Telegram channel?).
Now lets see some code:
from config import tgtoken, privchannID
from uuid import uuid4
from telegram import Bot, InlineQueryResultCachedPhoto
bot = Bot(tgtoken)
def inlinecachedphoto(update, context):
query = update.inline_query.query
if query == "/CachedPhoto":
infophoto = bot.sendPhoto(chat_id=privchannID,photo=open('logo.png','rb'),caption="some caption")
thumbphoto = infophoto["photo"][0]["file_id"]
originalphoto = infophoto["photo"][-1]["file_id"]
results = [
InlineQueryResultCachedPhoto(
id=uuid4(),
title="CachedPhoto",
photo_file_id=originalphoto)
]
update.inline_query.answer(results)
when you send a photo to a chat/group/channel, you can obtain the file_id, the file_id of the thumbnail, the caption and other details I'm going to skip. What the problem? If you don't filter the right query, you may end up sending the photo multiple times to your private channel. It also means the autocomplete won't work.
InlineQueryResultPhoto
The other alternative is upload the photo to internet and then use the url. Excluding options like your own hosting, you can use some free image hostings that provides APIs (for example: imgur, imgbb). For this code, generating your own key in imgbb is simpler than imgur. Once generated:
import requests
import json
import base64
from uuid import uuid4
from config import tgtoken, key_imgbb
from telegram import InlineQueryResultPhoto
def uploadphoto():
with open("figure.jpg", "rb") as file:
url = "https://api.imgbb.com/1/upload"
payload = {
"key": key_imgbb,
"image": base64.b64encode(file.read()),
}
response = requests.post(url, payload)
if response.status_code == 200:
return {"photo_url":response.json()["data"]["url"], "thumb_url":response.json()["data"]["thumb"]["url"]}
return None
def inlinephoto(update, context):
query = update.inline_query.query
if query == "/URLPhoto":
upphoto = uploadphoto()
if upphoto:
results = [
InlineQueryResultPhoto(
id=uuid4(),
title="URLPhoto",
photo_url=upphoto["photo_url"],
thumb_url=upphoto["thumb_url"])
]
update.inline_query.answer(results)
This code is similar to the previous method (and that includes the same problems): uploading multiple times if you don't filter the query and you won't have the autocomplete when writing the inline.
Disclaimer
Both code were written thinking the images you want to upload are generated at the moment you receive the query, otherwise you can do the work previous to receiving the query, saving that info in a database.
Bonus
You can run your own bot to get the channel_id of your private channel with pyTelegramBotAPI
import telebot
bot = telebot.TeleBot(bottoken)
#bot.channel_post_handler(commands=["getchannelid"])
def chatid(message):
bot.reply_to(message,'channel_id = {!s}'.format(message.chat.id))
bot.polling()
To get the id you need to write in the channel /getchannelid#botname

Telethon - Error when retrieve user info

I'm stuck with an error in telethon, when trying to get users data.
First, I get new messages from some groups, it's ok, but when I try to get user data (name, first_name etc) - sometimes it's ok, but mostly fails with error
ValueError: Could not find the input entity for "12345678".
Please read https://telethon.readthedocs.io/en/latest/extra/basic/entities.html
to find out more details.
I read that article a lot of times, tried to use also client.get_input_entity as it says, but it doesn't help
Here is my code:
import logging
from telethon import TelegramClient, events
logging.basicConfig(level=logging.WARNING)
logging.getLogger('asyncio').setLevel(logging.ERROR)
entity = 'session' # session
api_id = 123456
api_hash = 'hash'
phone = '1234567'
chats = ['group1', 'group2', 'group3']
client = TelegramClient(entity, api_id, api_hash)
#client.on(events.NewMessage(chats=chats))
async def normal_handler(event):
print(event.message.message)
print(event.date)
print(event.from_id)
print(event.message.to_id)
#user = await client.get_input_entity(event.from_id)
user = await client.get_entity(event.from_id)
client.start()
client.run_until_disconnected()
How can I fix that?
And one more question, how can I retrieve info about group?
I know it's id from event.message.to_id, but can't get how to get it's name.
The docs for the library looks not very friendly for beginners. =(
Thank you
Telegram does not allow to get user profile by integer id if current client had never "saw" it.
Telethon documentation (https://telethon.readthedocs.io/en/latest/extra/basic/entities.html) suggests following options to make contact "seen":
if you have open conversation: use client.get_dialogs()
if you are in same group: use client.get_participants('groupname')
if you are it was forward in group: use client.get_messages('groupname', 100)
Choose which one is applicable in your case. One of them will make contact "seen", and it will be possible to use client.get_entity(event.from_id)

Creating Slackbot with Google Sheets integration using python and git

My name is Ken. I am trying to create a Slack Bot first one message every Monday at 9:00 am and asks for a input (goal number of sales for the week). Then responds with user input in new message saying (great your weekly sales goal is (#). Then it takes this number and adds it to Google sheets. Then asks user to enter daily goal for the day. And responds with (daily goal set as). Then at 9:00 pm asks user to input the number of deals written and keeps track of all data in Google sheets and provides graphs. I have been thinking maybe MySQL would work for that too.
Here is some of the code I have so far:
starterbot.py
import os
import time
from slackclient import slackclient
# starterbot's ID as an environment variable
BOT_ID = os.environ.get("BOT_ID")
# contasts
AT_BOT = "<#" + BOT_ID + ">"
EXAMPLE_COMMAND = "do"
#instantiate Slack & Twilio clients
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
def handle_command (command, channel)
"""
Receives commnds directed at the bot and determines if they
are valid commands. if so, then acts on the commands. if not,
returns back what it needs for clarification.
"""
response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \
"* command with numbers, delimited by spaces."
if command.startswitch(EXAMPLE_COMMAND):
response = "Sure ... wire some more c ie then I can do
that!"
slack_client.api_call("chat.postMessage", channel=channel,
text=response, as_user=True)
def parse_slack_output(slack_messages):
"""
The Slack Real Time Messaging API is an event firehose.
this parsing function returns None unless a message is
directed at the Bot, based on its ID.
"""
if slack_messages and len(slack_messages) > 0;
for message in slack_messages:
if message and 'text' in message and AT_BOT in message['text']:
command = message['text'].split(AT_BOT)[1].strip().lower()
channel = message['channel']
# return text after the # mention, white space removed
return command, channel
return None, None
if __name__ == "__main__":
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print("starterbot connected and running!")
while True:
command, channel = parse_slack_output(slack_client.rtm_read())
if command and channel:
handle_command(command, channel)
time.sleep(READ_WEBSOCKET_DELAY)
else:
print("Connection failed. Invalid Slack token or bot ID?")
bot_id_py
import os
from slackclient import SlackClient
import pdb
BOT_NAME = 'pilot4u'
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
if __name__ == "__main__":
api_call = slack_client.api_call("users.list")
if api_call.get('members'):
pdb.set_trace()
# Retrieve all users so we can find our bot
users = api_call.get('members')
for user in users:
if 'name' in user and user.get('name') == BOT_NAME:
print("Bot ID for '" + user ['name'] + "'is " +
user.get('id'))
else:
print("could not find bot user with the name " + BOT_NAME)

Categories

Resources