I use Pyrogram — version 2.0 to create bot. I wanted to sing in/up to another number using the client I am connected to. That phone number may not have logged in to Telegram yet.
But when I use the "send_code" method, the session with which it used to connect gets terminated. I used API bot to get enough information (phone number, two-step verification, and code) and CLI bot to send code.
The code is like this:
import uvloop
from pyrogram import Client, filters
from pyrogram.types import Message
# Apply monkey patch listen
from pyromod import listen
uvloop.install()
api_bot = {
'name': 'my_bot',
'api_id': 5555555,
'api_hash': '932835f263b17eb623bd251d0',
'bot_token': '5225489486ZckBKhgGESKTHvZjQNuKXGtSHTpA'
}
proxy = {
"scheme": "socks5",
"hostname": "127.0.0.1",
"port": 9050,
}
client = Client(**api_bot, proxy=proxy)
async def login(name, phone_number, two_step_verification, chat_id) -> str or bool:
cli_bot = {
'name': '.....',
'api_id': 111111,
'api_hash': '...........',
'session_string': '...........................'
}
# In order to use the "send_code" method, we must connect to a client
async with Client(**cli_bot, proxy=proxy) as app:
await app.send_code(phone_number)
code = await app.ask(chat_id=chat_id,
text='send telegram code to me',
timeout=125)
# Connecting to the client whose number we received
async with Client(name, api_id, api_hash,
phone_number=phone_number,
phone_code=code,
in_memory=True,
password=two_step_verification,
proxy=proxy,
test_mode=True) as app:
session_string = await app.export_session_string()
if session_string:
with open(name + '.txt', 'w') as file:
string = (phone_number, two_step_verification, session_string, name)
file.write('\n'.join(string))
await client.send_message(chat_id, 'added successfully your phone number')
return True
#client.on_message(filters.private & (filters.contact | filters.text))
async def get_phone_number(app: Client, message: Message):
data = {'phone_number': '+11111111',
'name': 'jenny',
'two_step_verification': ''}
await(login(**data))
client.run()
and then get this error in line 34:
pyrogram.errors.exceptions.unauthorized_401.AuthKeyUnregistered: Telegram says: [401 AUTH_KEY_UNREGISTERED] - The key is not registered in the system. Delete your session file and login again (caused by "users.GetUsers")
Totally, I want to sign in/up to different accounts and extract their session-string. I don't know what is wrong with my code. Would you please guide me?
Related
How can i start a secret chat session using telethon? I've found a solution on the web; https://pypi.org/project/telethon-secret-chat/, but i'm not sure how it is supposed to work. I understand all the other stuff but what is supposed to go inside in the manager.start_secret_chat(target) function?
from telethon import TelegramClient
from telethon_secret_chat import SecretChatManager
client = TelegramClient('log', app_id, app_hash)
async def replier(event):
# all events are encrypted by default
if event.decrypted_event.message and event.decrypted_event.message == "hello":
await event.reply("**hi**") # parse_mode is markdown by default
async def new_chat(chat, created_by_me):
if created_by_me:
print("User {} has accepted our secret chat request".format(chat))
else:
print("We have accepted the secret chat request of {}".format(chat))
manager = SecretChatManager(client, auto_accept=True,
new_chat_created=new_chat) # automatically accept new secret chats
manager.add_secret_event_handler(func=replier) # we can specify the type of the event
with client:
client.run_until_disconnected()
manager.start_secret_chat(target)
Target can be the user_id. See this example:
# wait for incoming message
#client.on(events.NewMessage)
async def incoming_message_handler(event):
userId = event.original_update.user_id
# start secret chat
await manager.start_secret_chat(userId)
I'd like to call mutations from AppSync using my Python function but use a Cognito user for the authorization as "API-KEY", "IAM" and other methods are not suitable for my application.
My mutation looks like this (test purposes):
mutation XYZ {
updateTask(input: {id: "a1b2c3", name: "newTaskName"}) {
id
name
}
}
I am assuming that the user is already created and enabled by some means. If your AppSync API is secured only using Cognito, you are always going to need a username and a password to begin with. For example, you can use below code to login and get the AccessToken from the response:
import boto3
def get_user_auth(event, context):
client = boto3.client('cognito-idp')
response = client.initiate_auth(
UserPoolId='xxxxxxxxx',
ClientId='xxxxxxxxxxxxxx',
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={
'USERNAME': 'xxxxxx',
'PASSWORD': 'xxxxxx'
}
)
return response
Note: Make sure that you have "Enable username password based authentication (ALLOW_USER_PASSWORD_AUTH)" enabled.
Once you have the access token, you can use this in HTTP headers within your request as follows:
{
"authorization": "<YOUR-VERY-VERY-LONG-ACCESS-TOKEN>"
}
For example:
import requests
from requests_aws4auth import AWS4Auth
import boto3
session = requests.Session()
APPSYNC_API_ENDPOINT_URL = '<YOUR-API-URL>'
mutation = """mutation XYZ {updateTask(input: {id: "a1b2c3", name: "newTaskName"}) {id, name}}"""
response = session.request(
url=APPSYNC_API_ENDPOINT_URL,
method='POST',
headers={'authorization': '<YOUR-VERY-VERY-LONG-ACCESS-TOKEN>'},
json={'mutation': mutation}
)
print(response.json()['data'])
Since this access token has some expiration, you might also need to refresh this token by using the RefreshToken from the above response. Like so:
def refresh_token(self, username, refresh_token):
try:
return client.initiate_auth(
ClientId=self.client_id,
AuthFlow='REFRESH_TOKEN_AUTH',
AuthParameters={
'REFRESH_TOKEN': refresh_token,
# 'SECRET_HASH': self.get_secret_hash(username)
# If the User Pool has been defined with App Client secret,
# you will have to generate secret hash as well.
}
)
except botocore.exceptions.ClientError as e:
return e.response
Example of how you can generate secret hash.
I am making a discord bot that I plan on being in multiple servers. Each server will have a different welcome channel name and all that. I made the welcome message and I tried making the bot post the message in a channel called "welcome" which would solve this problem but didn't work. I thought about making a database that saves the channel id that the server owner sends to the bot under the server name/ID. The bot when triggered would match the server ID to one in the database then grab the channel id linked to the server id. But that would be a lot of coding in SQL or PostgreSQL which I would have to learn how to get the bot to save the sever id and channel id to the database, How to get the bot to match the server id's then grab the channel id and posting it the message to the server. There is no documentation on discord py bots and making welcome messages for different servers. I was wondering if there is a better way to do it and how would I do it?
What I have so far in relation to the welcome message.
import discord
import logging
import asyncio
import random
import time
import tweepy, discord
from discord.ext import commands
from discord.ext.commands import bot
#File Imports
from config import *
client = commands.Bot(command_prefix='sec.')
# logger = logging.getLogger('discord')
# logger.setLevel(logging.DEBUG)
# handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
# handler.setFormatter(logging.Formatter('%(name)s: %(message)s'))
# logger.addHandler(handler)
#client.event
async def on_ready():
print('Logged in as %s' % client.user.name)
while True:
presence = random.choice(['sec.help', 'Defending Servers'])
activity = discord.Game(name=(presence))
await client.change_presence(status=discord.Status.online, activity=activity)
await asyncio.sleep(7)
client.remove_command('help')
#client.event
async def on_member_join(member):
# Adds role to user
# role = discord.utils.get(member.server.roles, name='Member')
# await client.add_roles(member, role)
# Random embed color
range = [255,0,0]
rand = random.shuffle(range)
# Welcomes User
embed = discord.Embed(title="{}'s info".format(member.name), description="Welcome too {}".format(member.guild.name))
embed.add_field(name="Name", value=member.name, inline=True)
embed.add_field(name="ID", value=member.id, inline=True)
embed.add_field(name="Status", value=member.status, inline=True)
embed.add_field(name="Roles", value=member.top_role)
embed.add_field(name="Joined", value=member.joined_at)
embed.add_field(name="Created", value=member.created_at)
embed.set_thumbnail(url=member.avatar_url)
inlul = client.get_channel(CHANNEL_ID)
await inlul.send(inlul, embed=embed)
If you find any documentation on this I would love to read it. All I could find are for bots that are basic and has you enter a channel id.
If the bot is on a much smaller scale, say just a few servers, then I'd say using a json file to save a dictionary wouldn't be a bad idea.
You can save the Id of the top text channel as a default when the server joins the server and let them change what channel to use with commands, this can be done with the on_guild_join event
import json
#sets value in json to guild id upon the bot joining the guild
#client.event
async def on_guild_join(guild):
#loads json file to dictionary
with open("filename.json", "r") as f:
guildInfo = json.load(f)
guildInfo[guild.id] = guild.text_channels[0] #sets key to guilds id and value to top textchannel
#writes dictionary to json file
with open("filename.json", "w") as f:
json.dump(guildInfo, f)
#allows server members to set channel for welcome messages to send to
#client.command()
async def welcomeMessage(ctx):
with open("filename.json", "r") as f:
guildInfo = json.load(f)
guildInfo[ctx.message.guild.id] = ctx.message.channel.id #sets channel to send message to as the channel the command was sent to
with open("filename.json", "w") as f:
json.dump(guildInfo, f)
then just use
with open("filename.json", "r"):
guildInfo = json.load(f)
channnel = guildInfo[ctx.message.guild.id]
to get the channel to send the message to and
channel.send(embed=embed)
to send the message
before running it ensure to have an empty json file in the same directory and add {} to the file.
I know that a bot can be created in a telegram if you send the command /newbot to the bot #BotFather. But to do this, you need to take your device, open Telegram, open a chat with #BotFather and send him the command /newbot. Can all of the above be done programmatically?
P.S.: this is not laziness, but an attempt to optimize the solution.
Yes, it's possible to create such interaction with mtproto libraries (pyrogram, telethon, madelineproto, etc...)
Here is a PoC script using telethon (python3 -m pip install -U telethon first to install the dependency):
from telethon import TelegramClient, events
api_id = ...
api_hash = "..."
client = TelegramClient('session', api_id, api_hash)
BOT_NAME="..."
BOT_USER_NAME="..." # must end with -bot
#client.on(events.NewMessage)
async def message_handler(event):
if 'Please choose a name for your bot' in event.raw_text:
await event.reply(BOT_NAME)
elif 'choose a username for your bot' in event.raw_text:
await event.reply(BOT_USER_NAME)
elif 'Done! Congratulations on your new bot' in event.raw_text:
print("Bot created!")
await client.disconnect()
async def main():
await client.send_message('botfather', '/newbot')
with client:
client.loop.run_until_complete(main())
client.run_until_disconnected()
You acquire the app_id and app_hash values from https://my.telegram.org/
and here is telethon's doc.
I was trying to buid an app to send push notification throguh dialogflow fullfuillment to user. I followed this link, now I've got the update permission (see screenshot 1 and 2 at the bottom of the quetion). I followed the stackoverflow thread to write this piece of python code to send a notification, I'm able to run it, and got a status code of 200, but I never receive my test notification on my GoogleHomeApp/Google speaker. Can you help?
import io
import json
import requests
from google.oauth2 import service_account
import google.auth.transport.requests
PATH_TO_SERVICE_ACCOUNT = 'account.json'
REQUIRED_SCOPE = 'https://www.googleapis.com/auth/actions.fulfillment.conversation'
# Get access token
with io.open(PATH_TO_SERVICE_ACCOUNT, 'r', encoding='utf-8') as json_fi:
credentials_info = json.load(json_fi)
credentials = service_account.Credentials.from_service_account_info(
credentials_info, scopes=[REQUIRED_SCOPE])
request = google.auth.transport.requests.Request()
credentials.refresh(request)
headers = {
'Authorization': 'Bearer ' + credentials.token
}
text = 'Hello, this is a test notification'
user_id = "ABwppHFyNFT1fqDRmEug_k2ZKu43hM7xbLmgShN_ESww0iwPLQh-BU6n4T-e3rUOiVqRBWNn5q6bOg"
payload = {
'customPushMessage': {
'userNotification': {
'title': 'Recent News',
'text': text,
},
'target': {
'userId': user_id,
'intent': 'Recent News',
# Expects a IETF BCP-47 language code (i.e. en-US)
'locale': 'en-US'
}
}
}
r = requests.request("POST", 'https://actions.googleapis.com/v2/conversations:send', data=json.dumps(payload), headers=headers)
print(f"A push notification has been sent to user {user_id} with status code {r.status_code}.")
This is the screenshot of simulator:
This is the logs I got on my localhost, shows that I got the permission to send push notification to the user.
I went to the stackdriver logging to check the logs, this is what i got:
If you go to the Official Push Notifications Documentation you'll find the note which indicates that as of now, push notifications are not supported on the voice-activated speakers.
Soon they might release the update but we never know! You might ask the support team regarding the updates.