Global name is not defined telepot - python

When trying to sendMessage it tells me the chat id is not defined. I am able to answerCallbackQuery because it needs query ID not chat.
If I try to enter in 'chat_id' in the DEF on callback query area it throws up more errors
Where exactly in the code do I need to define it?
import sys
import time
import os
import telepot
from telepot.loop import MessageLoop
from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton
def on_chat_message(msg):
content_type, chat_type, chat_id = telepot.glance(msg)
#creating buttons
if content_type == 'text':
if msg['text'] == '/start':
bot.sendMessage(chat_id, 'Welcome to #UK_Cali Teleshop\n Created by JonSnow 2021',reply_markup = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Feedback",callback_data='a'), InlineKeyboardButton(text="You",callback_data='b'),InlineKeyboardButton(text="PGP",callback_data='c'), InlineKeyboardButton(text="Cunt",callback_data='d')],
[InlineKeyboardButton(text="Products",callback_data='e')]
]
))
def on_callback_query(msg):
query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
print('Callback Query:', query_id, from_id, query_data)
#find callback data
if query_data == 'a':
#bot.sendMessage(chat_id, 'dsuhsdd')
#answerCallbackQuery puts the message at top
bot.answerCallbackQuery(query_id, 'products')
bot = telepot.Bot('1646167995:AAGsOwfjcryYYkoah69QJ6XGA7koUywmuRk')
MessageLoop(bot, {'chat': on_chat_message,
'callback_query': on_callback_query}).run_as_thread()
print('Listening ...')
while 1:
time.sleep(10)

The chat_id variable is local to on_chat_message. on_callback_query does not have access to it. The most Pythonic method would make these into a class and store the chat id in a member variable, but you can do it here by adding
global chat_id
as the first line of on_chat_message. You don't need that in on_callback_query because you aren't changing the value, although it won't hurt.

Related

FSMstate error, cant connect mongo db to aiogram

I'm writing a telegram bot on aiogram and I've decided to use MongoDB as database for the project.
Unfortunately I'm stuck on the user balance feature.
I need to give user a balance and I need to have a possibility to change it.
from aiogram import types
from db import collection
from loader import dp
from states.balance_state import balance
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import FSMContext
import motor.motor_asyncio
from aiogram.contrib.fsm_storage.memory import MemoryStorage
import asyncio
storage=MemoryStorage()
#dp.message_handler(text='/balance', state = None)
async def change_balance(message: types.Message):
await message.answer('Amount')
await balance.amount.set()
async def check_balance(user_id: int, amount, now_balance):
try:
amount = int(amount)
if now_balance + amount >= 0:
await change_balance(user_id, amount)
return True
elif now_balance + amount < 0:
return 'no money'
except Exception:
return False
#dp.message_handler(state=balance.amount)
async def change_balance(message: types.Message, state: FSMContext):
user_id = message.chat.id
answer = message.text
await state.update_data(amount=answer)
check_balance = await check_balance(user_id=user_id, amount=answer)
now_balance = collection.find_one({"_id" : user_id})["money"]
new_balance = now_balance + answer
collection.update_one({"_id" : user_id}, {"$set" : {"money" : new_balance}})
if check_balance == 'no money':
await message.answer('error ')
await state.finish
elif check_balance:
await message.answer('Success')
await state.finish
else:
await message.answer('error')
await state.finish
Ive tried different options but none of them seems to work for some reason
Here is code for database
collection = cluster.Mafia_users.user
async def add_user(user_id, username):
date = datetime.now().date()
collection.insert_one({
"_id" : user_id,
"name" : username,
"date" : str(date),
"money" : int(1),
})
(cluster is connected but i havent add it here for safety purposes)
This is the error that appears in terminal when user writes /balance
FSMStorageWarning: You haven’t set any storage yet so no states and no data will be saved.
You can connect MemoryStorage for debug purposes or non-essential data.
await state.set_state(self.state)

Store info in an excel file from telegram bot

I want to program a telegram bot that collects information from people who want to join a project and stores this information in an excel file
from typing import NoReturn
from time import sleep
from email import *
from tkinter import*
from turtle import *
from telegram import*
import telegram
from telegram.ext import*
from xlsxwriter.workbook import Workbook
import pandas as pd
import openpyxl as xl
from telegram.error import NetworkError, Unauthorized
print('bot started....')
wb=''
full_name=''
birth_date=''
phone=''
ONE=""
TWO=""
THREE=''
x=0
FIRST=''
SECOND=''
users = {
# user_id:{'key':'value'}
}
UPDATE_ID = None
def echo (bot: telegram.Bot) -> None:
"""Echo the message the user sent."""
global UPDATE_ID
for update in bot.get_updates(offset=UPDATE_ID, timeout=10):
UPDATE_ID = update.update_id + 1
def start(update: Update, context: CallbackContext) :
global UPDATE_ID
if not UPDATE_ID in users:
users[UPDATE_ID] = {}
keyboard = [[InlineKeyboardButton(text="I want to join", callback_data='one')]]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text(text="Welcome", reply_markup=reply_markup)
def Aplly(update, context):
global full_name, birth_date, phone
full_name=''
birth_date=''
phone=''
x=0
query = update.callback_query
query.answer()
query.message.reply_text(text='Full name')
def handlmsg(update, context):
global x, full_name, birth_date, phone, chat_idd,university,College,year,email,address,Study_major,reasons
if x==0:
full_name={'full_name':update.message.text}
update.message.reply_text(text="birth day")
if x ==1:
birth_date={'birth_date':update.message.text}
update.message.reply_text(text="Phone")
if x ==2:
phone=update.message.text
update.message.reply_text(text="completed...")
print(full_name)
print(birth_date)
print(phone)
keyboard = [[InlineKeyboardButton(text="Confirm", callback_data='two')],
[InlineKeyboardButton(text="to retreat", callback_data='three')]]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text(text="Confirm", reply_markup=reply_markup)
return SECOND
def save(update,context):
global UPDATE_ID,wb
query = update.callback_query
query.answer()
query.edit_message_text(text="Done")
header =['full name', 'birth date', 'phone','chadt_id']
data = [full_name,birth_date, phone, UPDATE_ID]
wb = xl.load_workbook('sample.xlsx')
page = wb.active
page.title = 'companies'
page.append(header)
companies = [data]
for info in companies:
page.append(info)
wb.save('sample12.xlsx')
wb = xl.load_workbook('sample12.xlsx')
page = wb.active
sheet = wb['companies']
for i in range(1,sheet.max_row+1):
cell1=sheet.cell(row=i, column=10).value
x=int(UPDATE_ID)
if x==cell1:
page.delete_rows(i)
wb.save('sample112.xlsx')
doc_file = open('sample112.xlsx', 'rb')
return context.bot.send_document(844534481, doc_file)
def main() -> NoReturn:
"""Run the bot."""
updater = Updater('Tokn', use_context=True)
global UPDATE_ID
bot = telegram.Bot('tokn')
try:
UPDATE_ID = bot.get_updates()[0].update_id
except IndexError:
UPDATE_ID = None
while True:
try:
echo(bot)
except NetworkError:
sleep(1)
except Unauthorized:
UPDATE_ID += 1
updater = Updater('Tokn', use_context=True)
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(MessageHandler(Filters.text, handlmsg))
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start)],
states={
FIRST: [updater.dispatcher.add_handler(CallbackQueryHandler(Aplly, pattern='one'))],
SECOND: [updater.dispatcher.add_handler(CallbackQueryHandler(save, pattern='two')),
updater.dispatcher.add_handler(CallbackQueryHandler(Aplly, pattern='three'))]},
fallbacks=[CommandHandler('start', start)],)
updater.start_polling()
updater.idle()
main()
The problem occurs when two people want to use the bot at the same time, it treats them as one person
It stores their data in the same field
I think i need to use a dictionary but I didn't know how to relate it to the if and the counter

Retrieving data from 2 python scripts

This is the first script which get's data from a website:
import requests
def get_prices():
name = "SeedifyFund"
crypto_data = requests.get("https://api.pancakeswap.info/api/tokens").json()["data"]
data = None
for i in crypto_data:
current = crypto_data[i]
if current['name'] == name:
data = {
"PriceUSD": current["price"],
"PriceBNB": current["price_BNB"],
}
return data
if __name__ == "__main__":
print(get_prices())
The code above outputs the following: {'PriceUSD': '1.022239219137518991087869433174527', 'PriceBNB': '0.002452203037583603303073246037795846'}
I'm having issue an issue with the second script. I want it to use the data that it has collected above and print it in a telegram bot when the user types /price. The code for the second script:
import telegram
from telegram.ext import Updater
from telegram.ext import CommandHandler
from tracker import get_prices
telegram_bot_token = "API TOKEN"
updater = Updater(token=telegram_bot_token, use_context=True)
dispatcher = updater.dispatcher
def price(update, context):
chat_id = update.effective_chat.id
message = ""
crypto_data = get_prices()
for i in crypto_data:
bnbprice = crypto_data[i]["pricebnb"]
usdprice = crypto_data[i]["priceusd"]
message += f"1 SFUND = \n${usdprice:,.2f} USD\n{bnbprice:.3f} BNB\n\n"
context.bot.send_message(chat_id=chat_id, text=message)
dispatcher.add_handler(CommandHandler("price", price))
updater.start_polling()
When the user types /price in the telegram chat it give this error:
coin = crypto_data[i]["pricebnb"]
TypeError: string indices must be integers
Could someone tell me what I'm doing wrong and help me solve the issue. Many thanks

How to make Dynamic commands in telegram

How do you send an id for items in the data base with out creating a method for each id
My goal is to type the id desired /13 and the bot returns the info I need about that item
The repo of choice is pyTelegramBotAPI
for database access and manipulation I am using flask-sqlalchemy
import telebot
from config import telegram_token
bot = telebot.TeleBot(telegram_token)
#bot.message_handler(commands=['summary'])
def send_welcome(message):
summary = """ return general info about bot performance """
bot.reply_to(message, summary )
#bot.message_handler(commands=['<id>'])
def send_welcome(message):
id_ = """ return info about this id"""
bot.reply_to(message, id_)
Your link to API shows method with regex to recognize command
#bot.message_handler(regexp="SOME_REGEXP")
which you could use with regexp="/\d+" to get any /number.
And later you should use message.text[1:] to get this number as string (without /).
#bot.message_handler(regexp="/\d+")
def get_id(message):
id_ = message.text[1:] # as string without `/`
#id_ = int(message.text[1:]) # as integer
bot.reply_to(message, id_)
EDIT:
To run function only for /number it needs also ^ $
regexp="^/\d+$"
Without ^ $ it will run function also for hello /13 world
Minimal working code
import os
import telebot
TELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN')
bot = telebot.TeleBot(TELEGRAM_TOKEN)
#bot.message_handler(regexp="^\d+$")
def get_id(message):
id_ = message.text[1:] # as string without `/`
#id_ = int(message.text[1:]) # as integer
bot.reply_to(message, id_)
bot.polling()
EDIT:
You can also use
#bot.message_handler(func=lambda message: ...)
like
#bot.message_handler(func=lambda msg: msg.text[0] == '/' and msg.text[1:].isdecimal())
def get_id(message):
id_ = message.text[1:] # as string without `/`
#id_ = int(message.text[1:]) # as integer
bot.reply_to(message, id_)
or more readable
def is_number_command(message):
text = message.text
return text[0] == '/' and text[1:].isdecimal()
#bot.message_handler(func=is_number_command)
def get_id(message):
id_ = message.text[1:] # as string without `/`
#id_ = int(message.text[1:]) # as integer
bot.reply_to(message, id_)
You can use text[1:].isdecimal() or text[1:].isdigit() or text[1:].isnumeric() or str.isdecimal(text[1:]) or str.isdigit(text[1:]) or str.isnumeric(text[1:])
With func you can use other functions to make it even more complex.

TELEPOT Keep getting error 400 when chat not found when trying to call back query to send a message

This is my code, my conf.py file is just the API token which i have double checked and the timezone.
I am trying to get my bot to respond to a button click by sending a message or a photo. I understand i need to use the sendPhoto function but i dont know how to make it activate on the callback
import sys
import time
import os
import telepot
from telepot.loop import MessageLoop
from telepot.namedtuple import InlineKeyboardMarkup, InlineKeyboardButton
from telepot.delegate import (
per_chat_id, create_open, pave_event_space, include_callback_query_chat_id)
def on_chat_message(msg):
content_type, chat_type, chat_id = telepot.glance(msg)
if content_type == 'text':
if msg['text'] == '/start':
bot.sendMessage(chat_id, 'Welcome to #UK_Cali Teleshop\n Created by JonSnow 2021',reply_markup = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Feedback",callback_data='a'), InlineKeyboardButton(text="You",callback_data='b'),InlineKeyboardButton(text="PGP",callback_data='c'), InlineKeyboardButton(text="Cunt",callback_data='d')],
[InlineKeyboardButton(text="Products",callback_data='e')]
]
))
bot.sendMessage(chat_id, 'Quanti anni hai?', reply_markup=keyboard)
def on_callback_query(msg):
query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
print('Callback Query:', query_id, from_id, query_data)
if query_data=='a':
bot.sendMessage(query_id, 'ddd')
bot = telepot.Bot('1646167995:AAGsOwfjcryYYkoah69QJ6XGA7koUywmuRk')
MessageLoop(bot, {'chat': on_chat_message,
'callback_query': on_callback_query}).run_as_thread()
print('Listening ...')
while 1:
time.sleep(10)
you get your 400 error because the chat id is not quesry_id that represents the query, but from_id that represents the chat so:
def on_callback_query(msg):
query_id, from_id, query_data = telepot.glance(msg, flavor='callback_query')
print('Callback Query:', query_id, from_id, query_data)
if query_data=='a':
bot.sendMessage(from_id, 'ddd')

Categories