im new to discord py i want a command that will send a random image from a file and send it but i can get it to work i tried to use Discord bot to send a random image from the chosen file one but still could not get it to work so then i tried this but i still no work if anyone can help me plz do
#put your images into the image folder
#images that are uploaded will be moved to the sent_images folder so they won't be reposted
import discord,os,random,asyncio
from datetime import datetime
from discord.ext import commands
bot=commands.Bot(command_prefix='!')
send_time='12:00' #time is in 24hr format
image_channel_id='ChannelID' #channel ID to send images to, replace with your channel ID
image_types=('.jpg','.png','.gif','.jpeg') #add image types if needed
folders={'Image Folder':'images','Sent Folder':'sent_images'}
for folder in folders.values():
if not os.path.isdir(folder):
os.mkdir(folder)
#bot.event
async def on_ready():
print(bot.user.name)
print(bot.user.id)
async def send_image():
for item in os.walk('./{}'.format(folders['Image Folder'])):
images=list(pic for pic in item[2] if pic.lower().endswith(image_types))
if len(images) == 0:
await bot.send_message(image_channel,"Oops! I'm all out of images to send. Notify my owner!")
else:
image= random.choice(images)
await bot.send_file(image_channel,'./{}/{}'.format(folders['Image Folder'],image))
os.rename('./{}/{}'.format(folders['Image Folder'],image), './{}/{}'.format(folders['Sent Folder'],image))
async def time_check():
global image_channel
await bot.wait_until_ready()
image_channel=bot.get_channel(image_channel_id)
while not bot.is_closed:
now=datetime.strftime(datetime.now(),'%H:%M')
if now == send_time:
await send_image()
await asyncio.sleep(60)
bot.loop.create_task(time_check())
bot.run('TOKEN')```
From your question, I understood that you have a bunch of folders with a bunch of images in them and you want to make a command that sends a random image.
import os, random
#bot.command()
async def random_image(ctx, category: str = None):
root_dir = os.listdir('./images')
# If the user doesn't specify a category send a random image from a random folder
if category is None:
# Getting a random directory and file
dir = random.choice(root_dir)
image = random.choice(os.listdir(os.path.join(root_dir, dir)))
path = os.path.join(dir, image)
elif category in root_dir:
# Getting a random file from the category
image = random.choice(os.listdir(os.path.join(root_dir, category)))
path = os.path.join(dir, image)
else:
await ctx.send("Couldn't find that category")
return
# Sending the image in an embed
file = discord.File(path)
embed = discord.Embed(title=category.title(), colour=discord.Colour.greyple())
embed.set_image(url=f'attachments://{image}')
await ctx.send(file=file, embed=embed)
{prefix}random_image ← will send a random image from a random dir
{prefix}random_image dog ← will send a random image from ./images/dog dir
Let me know if that's what you were asking for.
#bot.command()
async def random_image(ctx):
Images = ['./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png']
await ctx.send(file=discord.File(f'{random.choice(Images)}'))
Related
I've been working on a private discord bot for a week or so now to get familiar with creating discord bots. All of my commands run fine and there are currently no known bugs except this one. For some reason, when my discord bot sends error messages from this function it will send a duplicate of the original embed it sent.
Here is my code:
#commands.Cog.listener()
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
if isinstance(error, commands.BadArgument):
embed = discord.Embed(
title = '!!! BAD ARGUMENTS !!!',
description = f'Please check your arguments and try again. Error: {error}',
color = 0xFF0000
)
elif isinstance(error, commands.MissingRole):
embed = discord.Embed(
title = '!!! MISSING PERMISIONS !!!',
description = f'You do not have permission to use this command.',
color = 0xFF0000
)
else:
embed = discord.Embed (
title = "!!! ERROR !!!",
description = "A unknown error has occured. This error has been logged and will be looked into shortly.",
color = 0xFF0000
)
with open("unkown_errors.txt", "a") as f:
f.write(f"{ctx} | {error}\n")
await ctx.send(embed = embed)
That code is what I'm using for basic error handling. It will decide the embed based on the error and send the embed at the end of the message. The odd thing is it will send the embed once, and then send the same one again immediately after. It will be the exact same except the embed color on the second one is not the same as the first, it goes back to the default color. I'm unsure of why this is happening and I've tried looking for a solution. Is there any way I can fix this? Screenshot:
#Verve!
The method that you are using is incorrect, I think you should try this:-
#commands.Cog.listener()
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
if isinstance(error, commands.BadArgument):
embed = discord.Embed(
title = '!!! BAD ARGUMENTS !!!',
description = f'Please check your arguments and try again. Error: {error}',
color = 0xFF0000
)
return await ctx.send(embed = embed)
elif isinstance(error, commands.MissingRole):
embed = discord.Embed(
title = '!!! MISSING PERMISIONS !!!',
description = f'You do not have permission to use this command.',
color = 0xFF0000
)
return await ctx.send(embed = embed)
else:
embed = discord.Embed (
title = "!!! ERROR !!!",
description = "A unknown error has occured. This error has been logged and will be looked into shortly.",
color = 0xFF0000
)
await ctx.send(embed=embed)
with open("unkown_errors.txt", "a") as f:
f.write(f"{ctx} | {error}\n")
return
Mostly this shall work, if it doesn't it might be a bug. If it is a bug please open a issue :- https://github.com/Pycord-Development/pycord/tree/master/
I am using the Discord API to make a bot that changes the role colour. When I run this code it produces no errors but does not change the color
import discord
import time
from discord.ext import commands
bot = commands.Bot(command_prefix='>')
colors = [0xFF0000, 0xF0A804, 0xFFFF00, 0x008000, 0x0000FF, 0x800080]
#bot.command()
async def rainbow(ctx):
username = ctx.message.author
print(username)
roleid = 123
role = discord.utils.get(username.guild.roles, id=roleid)
await username.add_roles(discord.utils.get(username.guild.roles, id=roleid))
await ctx.send('You found the Rainbow!') # (The rainbow hates you)
for i in range(6):
await role.edit(colour=discord.Colour(colors[i]))
time.sleep(0.5)
print(colors)
await username.remove_roles(discord.utils.get(username.guild.roles, id=roleid))
bot.run('bot token')
I'm having this problem as well. I've noticed that whenever you modify a role, after some time, you will no longer be able to modify it anymore for some reason. I'm still trying to figure out why.
I am trying to add an image to my tkinter GUI. However I keep receiving errors, in particular my image does not have a 'read' attribute. I have tried this with TIF, GIF and PNG formatted files but none seem to work. I have checked and other seems not to have a problem adding an a image in png format. I have a feeling the problem is obvious but I am missing it.
import tkinter as tk
from PIL import ImageTk, Image
class Window(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("Lifespan Data Analyser")
self.pack(fill=tk.BOTH, expand=1)
path = Image.open('I:/python_work/TemplateRack_GUI.tif')
img = ImageTk.PhotoImage(file = path) #problem is here I think
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
panel.image=img
root = tk.Tk()
root.geometry("400x300")
app = Window(root)
root.mainloop()
Receive this attribute error:
AttributeError: 'TiffImageFile' object has no attribute 'read'
AttributeError: 'JpegImageFile' object has no attribute 'read'
try with:
path = 'I:/python_work/TemplateRack_GUI.tif'
no open
with this change your code works well, try with another tif
I am building an application to continuously display an image fetched from an IP camera. I have figured out how to fetch the image, and how to also display the image using Tkinter. But I cannot get it to continuously refresh the image. Using Python 2.7+.
Here is the code I have so far.
import urllib2, base64
from PIL import Image,ImageTk
import StringIO
import Tkinter
URL = 'http://myurl.cgi'
USERNAME = 'myusername'
PASSWORD = 'mypassword'
def fetch_image(url,username,password):
# this code works fine
request = urllib2.Request(url)
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
request.add_header("Authorization", "Basic %s" % base64string)
result = urllib2.urlopen(request)
imgresp = result.read()
img = Image.open(StringIO.StringIO(imgresp))
return img
root = Tkinter.Tk()
img = fetch_image(URL,USERNAME,PASSWORD)
tkimg = ImageTk.PhotoImage(img)
Tkinter.Label(root,image=tkimg).pack()
root.mainloop()
How should I edit the code so that the fetch_image is called repeatedly and its output updated in the Tkinter window?
Note that I am not using any button-events to trigger the image refresh, rather it should be refreshed automatically, say, every 1 second.
Here is a solution that uses Tkinter's Tk.after function, which schedules future calls to functions. If you replace everything after your fetch_image definition with the snipped below, you'll get the behavior you described:
root = Tkinter.Tk()
label = Tkinter.Label(root)
label.pack()
img = None
tkimg = [None] # This, or something like it, is necessary because if you do not keep a reference to PhotoImage instances, they get garbage collected.
delay = 500 # in milliseconds
def loopCapture():
print "capturing"
# img = fetch_image(URL,USERNAME,PASSWORD)
img = Image.new('1', (100, 100), 0)
tkimg[0] = ImageTk.PhotoImage(img)
label.config(image=tkimg[0])
root.update_idletasks()
root.after(delay, loopCapture)
loopCapture()
root.mainloop()
I am making screenshots of videos with HTML5 canvas, the video is hosted elsewhere, everything works except toDataURL() because the canvas is dirty. So, I am wondering, is there any way I can save this canvas image on the computer?
I assume the answer is no but hoping for some hack to get this done, well any idea apart from downloading the video to my server and serving it from there...
The short answer is "No."
The longer answer might be yes.
Maybe your server can download the video and host it, then play it from your same domain?
If you control the server that is hosting the video you could enable cors.
(Or you could combine the two and have the video uploaded to a cors-enabled site that is not your own.)
Otherwise, you're out of luck.
What about, I haven't tried it yet, if you redraw the original canvas on another canvas which you then save to an image. (and use css or position the canvases over each other to "hide" the second canvas).
Will the second canvas be dirty?
(thinking about a technique like thisone)
I tried the copying of the canvas but this just returned the same dirty canvas error.
In the end to get this work I implemented a small service that would extract remote sources (videos) and make them look as though they were local i.e. by reading the source server side and writing out to my HTML/JS page. Once this was done it all worked fine.
I used Python / Flask to do this, here is the snippet. Not perfect in regards to handle partial content requests but should get someone going.
To use it I access my videos using: /remote?url=
from datetime import timedelta
from flask import make_response, request, current_app, Flask, url_for, render_template, Response
from functools import update_wrapper
import requests
import logging
import json
from werkzeug.datastructures import Headers
import httplib
import os
import subprocess
import base64
httplib.HTTPConnection.debuglevel = 1
app = Flask(__name__)
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
def crossdomain(origin=None, methods=None, headers=None,
max_age=21600, attach_to_all=True,
automatic_options=True):
if methods is not None:
methods = ', '.join(sorted(x.upper() for x in methods))
if headers is not None and not isinstance(headers, basestring):
headers = ', '.join(x.upper() for x in headers)
if not isinstance(origin, basestring):
origin = ', '.join(origin)
if isinstance(max_age, timedelta):
max_age = max_age.total_seconds()
def get_methods():
if methods is not None:
return methods
options_resp = current_app.make_default_options_response()
return options_resp.headers['allow']
def decorator(f):
def wrapped_function(*args, **kwargs):
if automatic_options and request.method == 'OPTIONS':
resp = current_app.make_default_options_response()
else:
resp = make_response(f(*args, **kwargs))
if not attach_to_all and request.method != 'OPTIONS':
return resp
h = resp.headers
h['Access-Control-Allow-Origin'] = origin
h['Access-Control-Allow-Methods'] = get_methods()
h['Access-Control-Max-Age'] = str(max_age)
if headers is not None:
h['Access-Control-Allow-Headers'] = headers
return resp
f.provide_automatic_options = False
return update_wrapper(wrapped_function, f)
return decorator
def stream_remote(url, headers=None):
logging.debug(headers)
range = headers["Range"]
logging.debug(range)
r = requests.get(url, stream=True, headers={"range":range})
logging.debug(r.headers)
for block in r.iter_content(1024):
if not block:
break
yield block
#app.route('/remote/')
def get_remote():
# Gets a remote file to make it look like it is local for CORS purposes
url = request.args.get("url", None)
resp_headers = Headers()
resp_headers.add('Accept-Ranges','bytes')
if url is None:
return "Error. No URL provided"
else:
headers = request.headers
logging.debug(headers)
return Response(stream_remote(url, headers),mimetype='video/mp4',headers=resp_headers)
if __name__ == '__main__':
app.debug = True
app.run(host="127.0.0.1", port=9001)