Store info in an excel file from telegram bot - python

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

Related

telegram bot breaks down when it is used by more than one person

After more than one person uses the bot, the error 2022-06-03 19:46:12,641 (init.py:648 MainThread) ERROR - TeleBot appears: "A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: message text is empty". I read a lot of things, but nothing helped
import telebot
from telebot import types
import gspread
from registration_sheet import gs, sh
from button import button1, button2, mm
token = 'token'
txt = open("C:/Users/nmash/Desktop/Cloud/terms_of_the_agreement.txt", encoding = "utf-8")
class Telegrambot():
def __init__(self, token):
super(Telegrambot, self).__init__()
self.bot = telebot.TeleBot(token)
self.message_handler()
self.start()
def start(self):
self.bot.polling(none_stop=True)
def message_handler(self):
#self.bot.message_handler(content_types=['text'])
def message_worker(message):
if message.text == '/start':
button1()
self.bot.send_message(message.from_user.id, txt.read(), reply_markup=mm)
#self.bot.send_message(message.from_user.id, "Вы приняли условия соглашения✅", reply_markup=mm)
if message.text == "Принять условия соглашения✅":
self.bot.send_message(message.from_user.id, "Вы приняли условия соглашения✅", reply_markup=types.ReplyKeyboardRemove())
self.registration(message)
def registration(self, message):
def message_han(message):
sent = self.bot.send_message(message.from_user.id, 'Введите своё имя:')
self.bot.register_next_step_handler(sent, reg)
def reg(message):
name = message.text
worksheet = sh.sheet1
values_list = worksheet.row_values(2)
number = 0
while True:
n = number + 1
number = n
values_list = worksheet.row_values(number)
if values_list == []:
userId = number
break
worksheet.append_row([name, userId])
self.bot.send_message(message.from_user.id, "Ваше имя: " + name + "\nВаше ID: " + str(number))
message_han(message)
Telegrambot(token=token)

Need to pass variable "update" to method news()

I'm trying to create a python telegram bot that send random news every x time, and it works when i give the method news() the chat_id statically directly on the method, I tried passing it directly on the method start(), that execute a run_repeating job like that:
def start():
context.job_queue.run_repeating(news(update=update, context=context), interval=newsTimer, first=1)
but after you run the command for the first time (and works) it trows a lot of errors.
Instead I hardcoded the chat_id inside the news() method.
Anyone has any hint on how could I pass the variable update to the news() method?
Here's my full code:
from dotenv import load_dotenv
import telegram.ext
import requests
import datetime
import random
import json
import os
load_dotenv()
token = os.getenv('TOKEN')
api = os.getenv('API')
languages = "en"
newsTimer = 600
query = "world"
pageSize = "100"
yesterday = str(datetime.datetime.now() - datetime.timedelta(days=1))
today = str(datetime.datetime.now())
api_url = "https://newsapi.org/v2/everything?q=" + query + "&from=" + yesterday + "&to=" + today + "&sortBy=popularity&pageSize=+"+ pageSize +"&apiKey=" + api
def start(update, context):
context.job_queue.run_repeating(news, interval=newsTimer, first=1)
def help(update, context):
update.message.reply_text("""
Available commands:
/start - start bot
/help - help
""")
def news(context):
response = requests.get(api_url)
json_data = json.loads(response.text)
i = random.randint(0, 99)
title = json_data['articles'][i]['title']
image = json_data['articles'][i]['urlToImage']
description = json_data['articles'][i]['description']
author = json_data['articles'][i]['author']
article = json_data['articles'][i]
if title is None:
title = "No title"
if image is None:
image = "https://www.alfasolare.ru/a_solar_restyle/wp-content/themes/consultix/images/no-image-found-360x260.png"
if description is None:
description = "No Content"
if author is None:
author = "No Author"
if article is None:
i = random.randint(0, len(json_data['articles']))
caption = "<a>" + title + "\n" + description + "\n Author: " + author + "</a>"
chat_id = "XXXXXXXXX" #my own chat id
context.bot.send_photo(
chat_id=chat_id,
photo=image,
caption=caption,
parse_mode=telegram.ParseMode.HTML
)
if __name__ == '__main__':
updater = telegram.ext.Updater(token, use_context=True)
dispatcher = updater.dispatcher
dispatcher.add_handler(telegram.ext.CommandHandler('start', start))
dispatcher.add_handler(telegram.ext.CommandHandler('help', help))
if updater.start_polling():
print("Bot started successfully!")
if updater.idle():
print("Bot stopped")
context.job_queue.run_repeating(news(update=update, context=context), interval=newsTimer, first=1)
this can't work since the callback argument of JobQueue.run_* must be a function. However, news(update=update, context=context) is the return value of that function call, which is None as news doesn't return anything.
To pass additional data to the job callback, you can use the context argument of JobQueue.run_*. This is also explained in PTBs wiki page on JobQueue and showcased in the timerbot.py example.
Disclaimer: I'm currently the maintainer of python-telegram-bot

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

Global name is not defined telepot

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.

Python Telegram Bot Conversation Method Not Working

I am writing a Telegram Bot for an Income/Expense project.
I have this code using python-telegram-bot:
#!/usr/bin/python
# -*- Coding : UTF-8 -*-
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, ConversationHandler
from settings.conf import conf
conf = conf()
updater = Updater(str(conf.token()))
SETUP ,USERNAME = range(2)
def start_method(bot, update):
""" Start Command """
startList = [["Register New Account","Integrate An Account"]]
chat_id = update.message.chat_id
replyText = update.message.text
text = """Hello And Welcome To [Bestoon](http://bestoon.ir).
This Bot Helps You Easily Access Your [Bestoon](http://bestoon.ir) Account.
Now, How Can I Help You?
"""
bot.sendChatAction(chat_id, "TYPING")
update.message.reply_text(text, parse_mode="Markdown",reply_markup=ReplyKeyboardMarkup(startList, one_time_keyboard=True))
return SETUP
def setup(bot, update):
"""Initialize The User Account For The First Time"""
chat_id = update.message.chat_id
if update.message.text == "Register New Account":
bot.sendChatAction(chat_id, "TYPING")
register_text = """Ok.
Now Send Me Your Bestoon Username.
"""
update.message.reply_text(register_text,reply_markup=ReplyKeyboardRemove())
print "Going For Username"
return USERNAME
elif update.message.text == "Integrate An Account":
bot.sendChatAction(chat_id, "TYPING")
update.message.reply_text("Sorry, Can\'t Integrate Now!", reply_markup=ReplyKeyboardRemove())
bot.sendMessage(update.message.chat_id, "Bye!")
return ConversationHandler.END
else:
bot.sendChatAction(chat_id, "TYPING")
update.message.reply_text("Invalid Command!")
def regUser(bot, Update):
chat_id = update.message.chat_id
bot.sendChatAction("chat_id", "TYPING")
update.message.reply_text("Registering Your Username")
return ConversationHandler.END
def cancel(bot, update):
bot.sendMessage(update.message.chat_id, "Bye!")
return ConversationHandler.END
conv_handler = ConversationHandler(
entry_points = [CommandHandler('start', start_method)],
states = {
SETUP: [MessageHandler(Filters.text, setup)],
USERNAME: [MessageHandler(Filters.text, regUser)]
},
fallbacks = [CommandHandler('cancel', cancel)]
)
updater.dispatcher.add_handler(conv_handler)
########## Starting Bot ##########
updater.start_polling()
updater.idle()
When I use /start it works until the Bot says:
Ok
Now Send Me Your Username
And after that it need to return Registering Your Username but it doesn't.
but I have access to /cancel command.
I need to know why this script doesn't call regUser function?
Ok I've found 2 errors wich fixed my problem.
in regUser:
first I used chat_id between double quotes,
and second I used Updater with capital U instead of updater.

Categories