Can anyone help me with this?
For the button, it shows: IndentationError: unexpected indent
#bot.command()
async def button(ctx):
await ctx.send("hello",components = [
[Button(label="hi",style="3",custom_id="button1"), Button(label="bye",style="4",custom_id="button2")]
])
interaction = await bot.wait_for("button_click", check = lambda i:i.custon_id == "button1" )
await interaction.send(content = "BUtton Clicked", ephemeral=True)
For the select, it only shows urmom...
#bot.command()
async def select(ctx):
await ctx.send("Select", components= [
Select(
placeholder = "Select Something",
options = [
SelectOption(label="A",value="A"),
SelectOption(label="B",value="B")
])
])
while True:
try:
select_interaction = await bot.wait_for("select_option")
await select_interaction.send(content = f"{select_interaction.values[0]} selected", emphemral=False)
except:
await ctx.send("urmom")
Related
const pdf = require('pdfkit')
const QR = require('qrcode')
const emailTickets = async (userEvent, tickets) => {
await createQRCodes(tickets)
await createTicketPDF(tickets, userEvent)
await sendGridEmail(emailDetails, true)
}
The problem seems to be that async/await isn't working properly for the createTicketPDF function.
When I run the above emailTickets function a blank pdf document is emailed. However, when I run it with the below setTimeOut, the pdf contains all the detail that I want.
const emailTickets = async (userEvent, tickets) => {
await createQRCodes(tickets)
await createTicketPDF(tickets, userEvent)
setTimeout(async() => {await sendGridEmail(emailDetails, true)}, 5000);
}
I would prefer a solution where the code waited for the createTicketPDF function to finish before calling the sendGridEmail function.
Below is the code for the createTicketPDF function:
const createTicketPDF = async (tickets, userEvent) => {
const doc = new pdf
doc.pipe(fs.createWriteStream(`./tickets/${tickets[0]._id}.pdf`))
await tickets.map(async(ticket, index)=> {
return(
await doc.fontSize(30),
await doc.text(userEvent.title),
await doc.fontSize(10),
await doc.moveDown(),
await doc.text(`Venue: ${userEvent.venue}, ${userEvent.address1} `),
await doc.moveDown(),
await doc.fontSize(20),
await doc.text(`Ticket ${index+1} of ${tickets.length}: ${ticket.ticketType}`),
await doc.image(`./qrCodes/${ticket._id}.png`, {
align: 'center',
valign: 'center'
}),
await doc.addPage()
)
})
doc.end()
}
I had a forEach loop in this function but replaced it with a map on learning that forEach loops don't work well with async await.
I have also tried using (const ticket of tickets){} but this didn't work either
VS code is suggesting that none of the awaits within the map do anything
For completeness, below is the createQRCodes. This function is working perfectly.
const createQRCodes = async (tickets) => {
let CreateQRCodes = tickets.map(ticket => {
return(
QR.toFile(`./qrCodes/${ticket._id}.png`, String([ticket._id, ticket.randomNumber, ticket.creationTime.getTime(), ticket.userEvent]))
)})
await Promise.all(CreateQRCodes)
}
Any ideas where I am going wrong
Twilio SendGrid developer evangelist here.
As far as I can tell from the documentation, PDFKit is a synchronous library. The only thing that is asynchronous is writing the PDF to disk. So your code should not need to await anything within the createTicketPDF function. You do need to listen for the stream to finish though, so you could return a promise that resolves when the stream is finished, like this:
const createTicketPDF = (tickets, userEvent) => {
const doc = new pdf
const stream = doc.pipe(fs.createWriteStream(`./tickets/${tickets[0]._id}.pdf`))
tickets.map((ticket, index)=> {
return(
doc.fontSize(30),
doc.text(userEvent.title),
doc.fontSize(10),
doc.moveDown(),
doc.text(`Venue: ${userEvent.venue}, ${userEvent.address1} `),
doc.moveDown(),
doc.fontSize(20),
doc.text(`Ticket ${index+1} of ${tickets.length}: ${ticket.ticketType}`),
doc.image(`./qrCodes/${ticket._id}.png`, {
align: 'center',
valign: 'center'
}),
doc.addPage()
)
})
doc.end()
const promise = new Promise((resolve) => {
stream.on("finish", () => {
resolve();
})
});
return promise;
}
const emailTickets = async (userEvent, tickets) => {
await createQRCodes(tickets)
await createTicketPDF(tickets, userEvent)
await sendGridEmail(emailDetails, true)
}
I am using this code. Output of the code always shows TypeError: page.waitForXpath is not a function. Puppeteer version: 8.0.0 and puppeteer-xpath version: 0.1.0 I have also used this command to upgrade: npm install https://github.com/GoogleChrome/puppeteer/ but that does not work. Here is my code:
const { expect } = require('chai');
const puppeteer = require('puppeteer');
var browser, page;
before(async () => {
browser = await puppeteer.launch({
headless: false,
defaultViewport: null,
devtools: false,
args: [
"--disable-web-security",
"--disable-features=IsolateOrigins,site-per-process",
"--window-size=1920,1080"
]
});
page = await browser.newPage();
})
describe("Search to google", async () => {
it("write something to searchbar", async () => {
await page.goto("https://www.google.com");
let searchBarSelector = '[name=q]';
await page.waitForSelector(searchBarSelector);
let [searchBarElement] = await page.$$(searchBarSelector);
await searchBarElement.type("JavaScript Tutorial");
// await page.type(searchBarSelector,"JavaScript Tutorial");
await page.keyboard.press("Enter");
let imageXpath = "//a[contains(text(),'Images')]";
await page.waitForXpath(imageXpath);
let imageTextElement = await page.$x(imageXpath);
expect(imageTextElement != null).equals(true);
})
})
after(async () => {
await browser.close();
})
Output:
You just have a typo: it is page.waitForXPath(), not page.waitForXpath().
See page.waitForXPath(xpath[, options]) in the docs.
When I use the stream command on my bot, it streams about 1min 30s of audio before cutting off and not playing audio, and it doesn't give error messages at the start or when cutting off. When I use the download and play command instead, it plays the whole song without errors or cutoffs.
Stream command:
async def play(ctx, *, search):
voiceChannel=ctx.message.author.voice.channel
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
query_string = urllib.parse.urlencode({
'search_query': search
})
htm_content = urllib.request.urlopen(
'http://www.youtube.com/results?' + query_string
)
search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode())
url = 'http://www.youtube.com/watch?v=' + search_results[0]
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
song_info = ydl.extract_info(url, download=False)
voice.play(discord.FFmpegPCMAudio(song_info["formats"][0]["url"]))
Download command:
async def download(ctx, *, search):
song_there = os.path.isfile("song.mp3")
try:
if song_there:
os.remove("song.mp3")
except PermissionError:
await ctx.send("Wait for the current playing music to end or use the 'stop' command")
return
voiceChannel=ctx.message.author.voice.channel
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
query_string = urllib.parse.urlencode({
'search_query': search
})
htm_content = urllib.request.urlopen(
'http://www.youtube.com/results?' + query_string
)
search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode())
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download(['http://www.youtube.com/watch?v=' + search_results[0]])
for file in os.listdir("./"):
if file.endswith(".mp3"):
os.rename(file, "song.mp3")
voice.play(discord.FFmpegPCMAudio("song.mp3"))
Alright, so I found the answer here on stackoverflow dot com at When playing audio, the last part is cut off. How can this be fixed? (discord.py). I quote, "This is a known issue when you try to make a bot which doesn't download the song it's playing. It is explained here : https://support.discord.com/hc/en-us/articles/360035010351--Known-Issue-Music-Bots-Not-Playing-Music-From-Certain-Sources"
Turns out you just needed to give FFMPEG options to reconnect and play the song as shown in the code below
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
#client.command(
name='play',
description='Streams audio from Youtube. Syntax: w!play [keyword(s)].')
async def play(ctx, *, search):
voiceChannel=ctx.message.author.voice.channel
await voiceChannel.connect()
voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
query_string = urllib.parse.urlencode({
'search_query': search
})
htm_content = urllib.request.urlopen(
'http://www.youtube.com/results?' + query_string
)
search_results = re.findall(r"watch\?v=(\S{11})", htm_content.read().decode())
url = 'http://www.youtube.com/watch?v=' + search_results[0]
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
song_info = ydl.extract_info(url, download=False)
voice.play(discord.FFmpegPCMAudio(song_info["formats"][0]["url"], **FFMPEG_OPTIONS))
For whatever reason, some
I'm coding my first music bot for discord and successfully tested it on the localhost. After that, I moved it on Heroku and installed FFmpeg buildpack for it. But for some reason, it doesn't work.
Here is proof that I installed FFmpeg buildpack on Heroku: Screen
Here is my code (that works well on localhost):
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/best',
'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s',
'restrictfilenames': True,
'noplaylist': True,
'nocheckcertificate': True,
'ignoreerrors': False,
'logtostderr': False,
'quiet': True,
'no_warnings': True,
'default_search': 'auto',
'source_address': '0.0.0.0'
}
ffmpeg_options = {
'options': '-vn'
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
#classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
#client.command()
async def join(ctx):
channel = ctx.message.author.voice.channel
if ctx.voice_client is not None:
return await ctx.voice_client.move_to(channel)
await channel.connect()
#client.command()
async def play(ctx, *, URL):
async with ctx.typing():
player = await YTDLSource.from_url(url)
ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('Now playing: {}'.format(player.title))
I'm using webdriverio and need to wait for an element to be in the viewport
So I tried
browser.waitUntil(async () => {
const b = await link.isDisplayedInViewport()
return b;
}, 5000, 'expected to be visible after 5s');
But somehow waitUntil wants a boolean not a Promise<boolean>
How can I fix this?
Update:
I use WebdriverIO in a NodeJs app as follows
const { remote } = require('webdriverio');
(async () => {
const browser = await remote({
logLevel: 'error',
path: '/',
capabilities: {
browserName: 'chrome'
}
});
await browser.url('https://example.com');
const link = await browser.$('.special-link');
const ok = await browser.waitUntil(async () => {
const b = await link.isDisplayedInViewport()
return b;
}, 5000, 'expected to be visible after 5s');
await link.click();
const title = await browser.getTitle();
console.log('Title was: ' + title);
await browser.deleteSession();
})().catch((e) => console.error(e));
source
In the options is don't see anything about with or without async/await. Furthermore I don't use a testing framework!
Sorry for the late answer. But if you are still looking for a solution, Please try this if you want to avoid aync/await
get link() { return browser.element('.special-link'); }
browser.waitUntil(() => this.link.isVisibleWithinViewport(), 20000, 'link not visible')
const elementWaitingToBeDisplayed = $("some element locators")
elementWaitingToBeDisplayed.waitForDisplayed(10000, false)
If you set the second argument of elementWaitingToBeDisplayed.waitForDisplayed to true it waits for the opposite.