I am trying to attach a pdf file in a MS Teams bot.
I get the following error " [on_turn_error] unhandled error: (BadArgument) Unknown attachment type". Would anyone know why it might not work?
The following is a portion of my code that concerns the error... unfortunately since it is a chatbot it is not appropriate to put the full code here.
Thank you for your advice.
class MyBot(ActivityHandler):
async def on_message_activity(self, turn_context: TurnContext):
elif str(turn_context.activity.text).upper() in {'PDF'}:
reply = Activity(type=ActivityTypes.message)
reply.text = "This is the pdf file."
reply.attachments = [self._get_inline_attachment()]
await turn_context.send_activity(reply)
#truncated#
def _get_inline_attachment(self) -> Attachment:
file_path = os.path.join(os.getcwd(), "TEST.pdf")
with open(file_path, "rb") as pdf_file:
dencoded_string = base64.b64encode(pdf_file.read()).decode()
return Attachment(
name="TEST.pdf",
content_type="application/pdf",
content_url=f"data:application/pdf;base64,{dencoded_string}",
)
#Nivedipa-MSFT indicated that the sample code for file sharing on MS Teams is avail here: https://github.com/microsoft/BotBuilder-Samples/blob/22fcff680a3e11006eb09b81ac5ed4de345933e2/archive/samples/python/56.teams-file-upload/bots/teams_file_bot.py
If I may add, "supportsFiles" has to be enabled in the manifest for this to work: https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema#bots and https://learn.microsoft.com/en-us/microsoftteams/platform/resources/bot-v3/bots-files#configure-your-bot-to-support-files
Related
So I was writing a python script using telebot and got an error
A request to the Telegram API was unsuccessful. Error code: 400.
Description: Bad Request: file must be non-empty
I have tried different methods from many forums, but nothing helps
import telebot
import random
import time
token = #token here
bot = telebot.TeleBot(token)
shit = ["C:\\Users\\glebc\\Documents\\source(bot)\\3wZ3.gif.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\65216814_456719028224290_7745639790787166208_n.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\doc_2022-03-10_16-41-49.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\doc_2022-03-10_16-42-04.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\doc_2022-03-10_16-42-39.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\giphy.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_0080.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_0835.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_1362.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_4698.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_4962.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_6359.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_7497.MOV", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_7909.MOV", "C:\\Users\\glebc\\Documents\\source(bot)\\IMG_9540.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\mp4.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\video.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\комочек тьмы.mp4", "C:\\Users\\glebc\\Documents\\source(bot)\\кот.mp4"]
video = open(shit[random.randint(0, len(shit)-1)], 'rb')
#bot.message_handler(commands=['start'])
def start_message(message):
bot.send_message(message.chat.id, 'hello message 1')
#bot.message_handler(commands=['haha'])
def haha_message(message):
while True:
bot.send_video(message.chat.id, vidos)
time.sleep(3600) #1 hour
#bot.message_handler(commands=['hehe'])
def shit_message(message):
bot.send_video(message.chat.id, vidos)
bot.infinity_polling()
Also i dont understand error cause i dont close file only open
Problem can be because you open file only once and you never close it and open again.
When it reads then it move special pointer which shows where to read next time. When it reads to the end of file then this pointer is moved to the end of file and when it tries to read again then it trires to read from the end of file and there is nothing to read and it may say that you have empty file.
After reading you may have to use vidoe.seek(0) to move pointer to the beginnig of file.
Or you should close and open it again. And this can be even more useful because at this moment you select random file only once and later it would use always the same path. You should use random inside loop.
#bot.message_handler(commands=['haha'])
def haha_message(message):
while True:
video = open( random.choice(shit), 'rb')
bot.send_video(message.chat.id, video)
video.close()
time.sleep(3600) # 1 hour
and the same in other functions
#bot.message_handler(commands=['hehe'])
def shit_message(message):
video = open( random.choice(shit), 'rb')
bot.send_video(message.chat.id, video)
video.close()
BTW:
telegram may has some methods to execute tasks periodically.
For example module python-telegram-bot has telegram.ext.jobqueue for this.
Full working code
For tests I set logging.DEBUG to see all error messages.
Normally telebot catchs all errors and hides them.
I also used with open() as video so it automatically closes file.
import os
import random
import logging
import telebot
# display errors
telebot.logger.setLevel(logging.DEBUG)
TOKEN = os.getenv('TELEGRAM_TOKEN')
bot = telebot.TeleBot(TOKEN)
all_videos = [
"C:\\Users\\glebc\\Documents\\source(bot)\\3wZ3.gif.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\65216814_456719028224290_7745639790787166208_n.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\doc_2022-03-10_16-41-49.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\doc_2022-03-10_16-42-04.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\doc_2022-03-10_16-42-39.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\giphy.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_0080.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_0835.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_1362.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_4698.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_4962.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_6359.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_7497.MOV",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_7909.MOV",
"C:\\Users\\glebc\\Documents\\source(bot)\\IMG_9540.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\mp4.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\video.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\комочек тьмы.mp4",
"C:\\Users\\glebc\\Documents\\source(bot)\\кот.mp4"
]
#bot.message_handler(commands=['start'])
def start_message(message):
bot.send_message(message.chat.id, 'hello message 1')
#bot.message_handler(commands=['haha'])
def haha_message(message):
while True:
with open(random.choice(all_videos), 'rb') as video:
bot.send_video(message.chat.id, video)
time.sleep(3600) # 1 hour
#bot.message_handler(commands=['hehe'])
def shit_message(message):
with open(random.choice(all_videos), 'rb') as video:
bot.send_video(message.chat.id, video)
bot.infinity_polling()
As I said already sorry for the title. I have never worked with Azure API and have no idea what is wrong with the code, as I just copied from the documentation and put in my information.
Here is the code:
from azure.cognitiveservices.speech import AudioDataStream, SpeechConfig, SpeechSynthesizer, SpeechSynthesisOutputFormat
from azure.cognitiveservices.speech.audio import AudioOutputConfig
speech_config = SpeechConfig(subscription="ImagineHereAreNumbers", region="westeurope")
speech_config.speech_synthesis_language = "en-US"
speech_config.speech_synthesis_voice_name = "ChristopherNeural"
audio_config = AudioOutputConfig(filename=r'C:\Users\TheD4\OneDrive\Desktop\SpeechFolder\Azure.wav')
synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
synthesizer.speak_text_async("A simple test to write to a file.")
Well as I run this I get no error and in fact, get in my desired folder a .wav file, but this file has 0 bytes and it looks corrupted.
Now here is why I have no idea of what's wrong because if I remove this
speech_config.speech_synthesis_language = "en-US"
speech_config.speech_synthesis_voice_name = "ChristopherNeural"
So it becomes this
from azure.cognitiveservices.speech import AudioDataStream, SpeechConfig, SpeechSynthesizer, SpeechSynthesisOutputFormat
from azure.cognitiveservices.speech.audio import AudioOutputConfig
speech_config = SpeechConfig(subscription="ImagineHereAreNumbers", region="westeurope")
audio_config = AudioOutputConfig(filename=r'C:\Users\TheD4\OneDrive\Desktop\SpeechFolder\Azure.wav')
synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
synthesizer.speak_text_async("A simple test to write to a file.")
It now works all of the sudden, but with what I assume to be the basic/common voice.
So here is my question: how do I choose a voice that I want(btw is this one "en-US-JennyNeural" style="customerservice" or something among these lines)
Thank You in advance!
ChristopherNeural is not a valid voice name. The actual name of the voice is en-US-ChristopherNeural.
speech_config.speech_synthesis_voice_name = "en-US-ChristopherNeural"
This is well-documented on the Language support page of the Speech services documentation.
For other, more fine-grained control over voice characteristics, you'll require the use of SSML as outlined in text-to-speech-basics.py.
I am building a bot that sends a txt file based on a command.
Problem is that when two people send the same command at the same time, the bot only sends one of the two twice, which is something I should avoid at all costs.
Do you have any solutions?
I tried to come up with a solution but it didn't work: I tried to delete the file right after it has been sent, but as I said, it didn't work.
NOTE: the bot successfully sends two embeds with the correct information, but then sends two identical files (always the one generated by the second request)
Here's the code of the command:
#bot.command(name='sendfile', help='Sends a file', pass_context=True)
async def quick(ctx, *args):
try:
arg1 = str(args[0])
arg2 = args[1].capitalize()
arg3 = args[2].upper()
quantity = args[3]
generate_file(order_id, arg2, quantity)
except:
embed = Embed(title="FILE GENERATION", description="An error has occurred. Please retry", color=16711702)
fields = [("Error ID", "1", False)]
for name, value, inline in fields:
embed.add_field(name=name, value=value, inline=inline)
print(f"{bcolors.FAIL} [{datetime.now()}] - ERROR {bcolors.ENDC}")
raise TypeError
embed = Embed(title="FILE GENERATION", description="FILE DETAILS", color=15859711)
fields = [("ARG 1", f"{arg1}", False), ("Arg2", f"{arg2}", False), ("arg3", f'{arg3}',False), ("Quantity", f"{quantity}", False)]
for name, value, inline in fields:
embed.add_field(name=name, value=value, inline=inline)
await ctx.send(embed=embed)
print(f"{bcolors.OKCYAN} [{datetime.now()}] - Command successfully executed! {bcolors.ENDC}")
with open("generated_file.txt", "rb") as file:
await ctx.send(file=discord.File(file, "generated_file.txt"))
Thanks for your help :)
The solution I came up with it solves the problem but it's not the best, but it works.
The idea is basically that I generate an alphanumeric string and include that in the file name.
e.g.: 'file_fu56d.txt'
After creation, I send it over to discord and then delete it.
Here's some code:
list= []
random_string = get_random_string(5)
for p in range(0, int(quantity)):
to_append = f'{arg1}-something-{arg2}-soimething_else-{arg2}\n'
list.append(to_append)
# writes the txt file assigning each element of the list to each line
with open(f'file_{random_string}.txt', 'w') as file:
file.writelines(list)
print(f'[{datetime.now()}] - {quantity} lines successfully generated.')
# opens the file and sends it to discord
with open(f"file_{random_string}.txt", "rb") as file:
await ctx.send(file=discord.File(file, f"file_{random_string}.txt"))
print(f"[{datetime.now()}] - File successfully sent! ")
# deletes the file
os.remove(f'file_{random_string}.txt')
print(f"[{datetime.now()}] - 'file_{random_string}.txt' successfully deleted!")
So i'm making some scoring system type thing in python with json and discord.py, this is its code:
import json
def getPoints(bot, user):
f = open('points.json', 'r')
points = json.load(f)
name = str(user)
f.close()
return points.get(name)
#later on down the line
#bot.group()
async def pointSystem(ctx):
pass
#pointSystem.command()
async def enable(ctx):
f = open('points.json', 'r')
points = json.load(f)
if points.get(str(ctx.author)) != None:
await ctx.send('Already enabled for this user!')
return
io = await ui.prompt(ctx, 'This command enables the point system\nAre you sure you want to enable this?')
if io == 'yes':
await ctx.send('Ok, enabling...')
points[str(ctx.author)] = 0
f.close()
f = open('points.json', 'w')
json.dump(points, f, indent=4)
f.close()
await ctx.send('Enabled for this user!')
else:
await ctx.send('Alright, stopping command execution...')
f.close()
in points.json i should have:
{}
And that's what i put in there originally, but sometimes, i look into points.json and i see a string with some random word in it. It doesn't give an error of any kind, it just does what i described, which doesn't make much sense, because i don't think i have any code that would set it to a string of any kind. I have no reproduction code, as i don't know the real culprit of this problem, i would point you towards doing something like what i did, which is creating a discord bot with this scoring system thing, but i don't really think even that would reproduce it.
Edit: Okay, this is getting really weird. 3 months later, with completely new code, I still have a file named "points.json" in my root directory, and it contains the random string I mentioned above, that literally makes no sense. Even when I remove it, a couple weeks later it will come back.
OK, I have been trying to think of a solution/find a solution myself for quite some time but everything I am attempting either ends up not a solution, or too complex for me to attempt without knowing it will work.
I have a discord bot, made in python. The bots purpose is to parse a blog for HTML links, when a new HTML link is posted, it will the post the link into discord.
I am using a textfile to save the latest link, and then parsing the website every 30seconds to check if a new link has been posted by comparing the link at position 0 in the array to the link in the textfile.
Now, I have managed to host my bot on Heroku with some success however I have since learned that Heroku cannot modify my textfile since it pulls the code from github, any changes are reverted after ~24hours.
Since learning this I have attempted to host the textfile on an AWS S3 bucket, however I have now learned that it can add and delete files, but not modify existing ones, and can only write new files from existing files on my system, meaning if I could do this, I wouldn't need to do this since I would be able to modify the file actually on my system and not need to host it anywhere.
I am looking for hopefully simple solutions/suggestions.
I am open to changing the hosting/whatever is needed, however I cannot pay for hosting.
Thanks in advance.
EDIT
So, I am editing this because I have a working solution thanks to a suggestion commented below.
The solution is to get my python bot to commit the new file to github, and then use that commited file's content as the reference.
import base64
import os
from github import Github
from github import InputGitTreeElement
user = os.environ.get("GITHUB_USER")
password = os.environ.get("GITHUB_PASSWORD")
g = Github(user,password)
repo = g.get_user().get_repo('YOUR REPO NAME HERE')
file_list = [
'last_update.txt'
]
file_names = [
'last_update.txt',
]
def git_commit():
commit_message = 'News link update'
master_ref = repo.get_git_ref('heads/master')
master_sha = master_ref.object.sha
base_tree = repo.get_git_tree(master_sha)
element_list = list()
for i, entry in enumerate(file_list):
with open(entry) as input_file:
data = input_file.read()
if entry.endswith('.png'):
data = base64.b64encode(data)
element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
element_list.append(element)
tree = repo.create_git_tree(element_list, base_tree)
parent = repo.get_git_commit(master_sha)
commit = repo.create_git_commit(commit_message, tree, [parent])
master_ref.edit(commit.sha)
I then have a method called 'check_latest_link' which checks my github repo's RAW format, and parses that HTML to source the contents and then assigns that content as a string to my variable 'last_saved_link'
import requests
def check_latest_link():
res = requests.get('[YOUR GITHUB PAGE LINK - RAW FORMAT]')
content = res.text
return(content)
Then in my main method I have the follow :
#client.event
async def task():
await client.wait_until_ready()
print('Running')
while True:
channel = discord.Object(id=channel_id)
#parse_links() is a method to parse HTML links from a website
news_links = parse_links()
last_saved_link = check_latest_link()
print('Running')
await asyncio.sleep(5)
#below compares the parsed HTML, to the saved reference,
#if they are not the same then there is a new link to post.
if last_saved_link != news_links[0]:
#the 3 methods below (read_file, delete_contents and save_to_file)
#are methods that simply do what they suggest to a text file specified elsewhere
read_file()
delete_contents()
save_to_file(news_links[0])
#then we have the git_commit previously shown.
git_commit()
#after git_commit, I was having an issue with the github reference
#not updating for a few minutes, so the bot posts the message and
#then goes to sleep for 500 seconds, this stops the bot from
#posting duplicate messages. because this is an async function,
#it will not stop other async functions from executing.
await client.send_message(channel, news_links[0])
await asyncio.sleep(500)
I am posting this so I can close the thread with an "Answer" - please refer to post edit.