In my interactions.py code, I have two different bot commands. One to get information about a user's products and one to retrieve a certain product. Whenever I run my code, I get AttributeError: 'Command' object has no attribute '_options'.
This is my code:
import interactions, requests
bot = interactions.Client(token="tokenhere")
#bot.command(
name="products",
description="Get a list of all your products",
scope=scopeid,
)
#interactions.option('Your roblox UserID',name='UserID', type=interactions.OptionType.INTEGER , required=True)
#bot.command(
name="retrieve",
description="Retrieve a certain product that you own",
scope=scopeid,
options=[
interactions.Option(
name='product',
description='the product you would like to retrieve',
type=interactions.OptionType.STRING,
required=True
)
]
)
async def products(ctx: interactions.CommandContext, userid: int):
a = str(requests.get('https://jedistuff22.pythonanywhere.com/products/' + str(userid)).text)
await ctx.send(a)
async def retrieve(ctx: interactions.CommandContext, product: str):
a = ctx.author.user.username + '#' + ctx.author.user.discriminator
print(a)
await ctx.send(a)
bot.start()
For some reason, my code works when i just have one command but just flat out stops working when I have two.
I'm really stumped with this error. I have been looking online for about the past day and I am yet to find something that could help me.
You've used the same bot.command() decorator to define two bot commands. Because the bot.command() method can only define one command at a time, you must define each command separately.
import interactions
import requests
bot = interactions.Client(token="tokenhere")
#bot.command(
name="products",
description="Get a list of all your products",
scope=scopeid,
)
#interactions.option('Your roblox UserID',name='UserID', type=interactions.OptionType.INTEGER , required=True)
async def products(ctx: interactions.CommandContext, userid: int):
a = str(requests.get('https://jedistuff22.pythonanywhere.com/products/' + str(userid)).text)
await ctx.send(a)
#bot.command(
name="retrieve",
description="Retrieve a certain product that you own",
scope=scopeid,
)
#interactions.option(
name='product',
description='the product you would like to retrieve',
type=interactions.OptionType.STRING,
required=True
)
async def retrieve(ctx: interactions.CommandContext, product: str):
a = ctx.author.user.username + '#' + ctx.author.user.discriminator
print(a)
await ctx.send(a)
bot.start()
Related
Im currently making a help command which should show the default embed which is the fun commands page, and having a select list with the default as "Fun commands". What I want to happen is so that when I choose the select list option as "General commands", it will edit the message with the general commands embed and the same select list but with the default set to "General commands instead of "Fun commands".
if message.content.startswith('c!help'):
select = Select(
placeholder = "Choose a category",
options=[
discord.SelectOption(
label="Fun commands",
description="j"),
discord.SelectOption(
label="General commands",
description="j3")
])
view = View()
view.add_item(select)
await message.channel.send(embed=fhelp,view=view)
async def call_back(interaction):
mainthing = select.values[0]
if mainthing == "Fun commands":
await interaction.response.edit_message(embed=fhelp,view=view)
elif mainthing == "General commands":
await interaction.response.edit_message(embed=ghelp,view=view)
select.callback = call_back
I'm trying to figure out how I can set an "expiration timer" on a message sent by a Telegram bot, containing a few buttons.
Long story short, there's a function which selects a random picture from a folder, then sends it to a group, and in a separate message it sends an InlineKeyboard object with some buttons for the picture to be rated
def send_stuff(context: CallbackContext):
job = context.job
keyboard = [
[
InlineKeyboardButton("NEVER", callback_data="NEVER"),
InlineKeyboardButton("UNLIKELY", callback_data="UNLIKELY")
],
[
InlineKeyboardButton("MEH", callback_data="MEH"),
InlineKeyboardButton("MAYBE", callback_data="MAYBE")
],
[
InlineKeyboardButton("YES", callback_data="YES"),
InlineKeyboardButton("ABSOLUTELY", callback_data="ABSOLUTELY")
],
[
InlineKeyboardButton("RATHER NOT SAY", callback_data="UNKNOWN")
]
]
reply_markup = InlineKeyboardMarkup(keyboard)
context.bot.send_photo(job.context, photo=open(PATH+thefile, 'rb'))
context.bot.send_message(job.context, text='RATE', reply_markup=reply_markup)
This function is being run by a run_daily job:
def start(update: Update, context: CallbackContext):
job = context.job
chat_id = update.message.chat_id
context.job_queue.run_daily(
send_stuff,
datetime.time(13, 45, 00, 000000, tzinfo=pytz.timezone('Europe/Bucharest')),
days=tuple(range(7)),
context=chat_id,
name='j1'
)
Then there is a handler for the user input, which edits the last message sent by the bot:
def main_handler(update: Update, context: CallbackContext):
update.callback_query.answer()
if update.callback_query.data is not None:
user_input = update.callback_query.data
update.effective_message.edit_text('VERDICT: ' + user_input)
What I'm trying to do is set some kind of "expiration" on the message containing the inline keyboard buttons, such that if there is no click by a user in say... 4 hours, it automatically edits itself into something like "NO ANSWER GIVEN".
I'm not super experienced with bots, and looking through the documentation of the telegram bot libraries I have not been able to find a way to do it.
Any suggestions are appreciated.
Thanks!
You apparently already know how to use PTBs JobQueue, so I'm sure that you can figure out how to schedule a new job from within the send_stuff function that edits the sent message :) All you need for that is context.job_queue.run_once and the return value of context.bot.send_message(job.context, text='RATE', reply_markup=reply_markup).
Disclaimer: I'm currently the maintainer of python-telegram-bot.
Thanks to user #CallMeStag I implemented the following solution.
def send_stuff(context: CallbackContext):
job = context.job
keyboard = [
[
InlineKeyboardButton("NEVER", callback_data="NEVER"),
InlineKeyboardButton("UNLIKELY", callback_data="UNLIKELY")
],
[
InlineKeyboardButton("MEH", callback_data="MEH"),
InlineKeyboardButton("MAYBE", callback_data="MAYBE")
],
[
InlineKeyboardButton("YES", callback_data="YES"),
InlineKeyboardButton("ABSOLUTELY", callback_data="ABSOLUTELY")
],
[
InlineKeyboardButton("RATHER NOT SAY", callback_data="UNKNOWN")
]
]
reply_markup = InlineKeyboardMarkup(keyboard)
context.bot.send_photo(job.context, photo=open(PATH+thefile, 'rb'))
# return values of send_message are saved in the 'msg' var
msg context.bot.send_message(job.context, text='RATE', reply_markup=reply_markup)
# the following job is created every time the send_stuff function is called
context.job_queue.run_once(
callback=cleanup,
when=5,
context=msg,
name='cleanup'
)
# the function called by the job
def cleanup(context: CallbackContext):
job = context.job
context.bot.edit_message_text(
chat_id=job.context.chat.id,
text='NO ANSWER PROVIDED',
message_id=job.context.message_id
)
i just started learning FastAPI, and i just created some model with ForeingKey(using tortoise), and in my route i have:
class DailyMontage(models.Model):
id = fields.IntField(pk=True, indexed=True)
team = fields.ForeignKeyField("models.Team", related_name="daily_montage", on_delete=fields.CASCADE)
type = fields.CharEnumField(utils.TypeDailyMontageUtils)
day_montage = fields.CharEnumField(utils.DayMontageUtils)
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
DailyMontage_Pydantic = pydantic_model_creator(DailyMontage, name="DailyMontage", exclude=('created_at', 'updated_at',))
DailyMontageIn_Pydantic = pydantic_model_creator(DailyMontage, name="DailyMontageIn", exclude_readonly=True)
#daily_route.post('/daily/create')
async def create_daily(daily: DailyMontageIn_Pydantic):
daily_obj = await DailyMontage.create(**daily.dict(exclude_unset=True))
return await DailyMontage_Pydantic.from_tortoise_orm(daily_obj)
but in my localhost/docs when i want add object, i only see 2 fields like type and day_montage, i dont see team, whenever i add it manualy like team_id i have error like not permitt to add it
i was searching everywhere where i know, but everythink what is in google i only see basics models ..
SOLVED:
okay i solved my problem now is display list of items from Enum and added team_id to put:
#monter_route.post('/daily/create', tags=['Daily'])
async def create_daily(type_daily: TypeDailyMontageUtils, day_montage: DayMontageUtils,
team_id: int, ):
team = await Team.get(id=team_id)
daily_obj = await DailyMontage.create(type=type_daily, day_montage=day_montage, team=team)
return await DailyMontage_Pydantic.from_tortoise_orm(daily_obj)
I encountered such a problem, I do not know how to set the name of this collection through the code when creating a collection, that is, I write:
cluster = MongoClient("link")
db = cluster.BananiData
collection = db.ctx.guild.id
but the name is set as ctx.guild.id, I need to insert the server ID in the name, how can this be implemented?
P.S: I use python
code:
cluster = MongoClient("mongodb+srv://Bananchik:hdkkIFkk6VKywSDH#cluster0.olcto.mongodb.net/<BananiData>?retryWrites=true&w=majority")
db = cluster.BananiData
collection = db.ctx.guild.id
#collection = cluster.BananiData.LevelSystem
class DataBases(commands.Cog):
""" ФСБ? """
def __init__(self, bot):
self.bot = bot
#commands.command()
#commands.check(permissions.is_owner)
async def test_db(self, ctx):
await ctx.send(collection)
await ctx.send("DB id created")
for member in ctx.guild.members:
print(member)
post = {
"_id": member.id,
"xp": 0,
"lvl": 1,
"message_count": 0
}
if collection.count_documents({"_id": member.id}) == 0:
collection.insert_one(post)
print(f"Пользователь **{member.name}** добавлен в базу данных")
It is a good practice to enclose the name you want to assign to a collection inside a
square bracket if you are using python.
Example:
If you want to create a collection by the name "SampleCollection", you could use the below command, even though
. operator works.
collection = db["SampleCollection"]
Therefore,
You should change the collection initialization code like the following:
collection = db[ctx.guild.id]
Note: Make sure that ctx.guild.id variable is of type str else it won't work.
So I want to get the json keys and compare them with the variable q
Json file
{
"api_key": "YOUR AUTOBUY API KEY",
"prefix": "PREFIX FOR BOT COMMANDS (for e.x !redeem, ?claim, etc",
"redeem_message": "Thanks for redeeming your order for {0}, I have added the ROLE_NAME_HERE role.",
"role_id": "REPLACE THIS WITH THE ID OF THE ROLE YOU WANT TO GIVE UPON REDEEMING",
"redeem_channel_id": "REPLACE THIS WITH THE CHANNEL ID WHERE PEOPLE CAN USE THE REDEEM COMMAND",
"bot_token": "PUT YOUR DISCORD BOT TOKEN HERE"
}
Code
import json
def search(q):
with open("config.json") as f:
data = json.load(f)
for obj in data:
print(data[obj])
search(q="role_id")
Expected output: REPLACE THIS WITH THE ID OF THE ROLE YOU WANT TO GIVE UPON REDEEMING (cause q = role_id and I want it to return the value of the key)
Actual output:
YOUR AUTOBUY API KEY
PREFIX FOR BOT COMMANDS (for e.x !redeem, ?claim, etc
Thanks for redeeming your order for {0}, I have added the ROLE_NAME_HERE role.
REPLACE THIS WITH THE ID OF THE ROLE YOU WANT TO GIVE UPON REDEEMING
REPLACE THIS WITH THE CHANNEL ID WHERE PEOPLE CAN USE THE REDEEM COMMAND
PUT YOUR DISCORD BOT TOKEN HERE
Super simple, no need for a for loop if you just need one value:
import json
def search(q):
with open("config.json") as f:
data = json.load(f)
print(data[q])
search(q="role_id")
below
data = {'A':12,'B':13}
q = 'A2'
value = data.get(q)
if value is not None:
print(value)
else:
print('{} not found'.format(q))