I am currently trying to migrate most of my code into cogs and I have this function that logs commands.
async def logging(self, ctx, command):
output = client.get_channel(channel_id_here)
embed = discord.Embed(title = "{} command used.".format(command), color = 0x40558a)
embed.add_field(name = "User:", value = "{}".format(ctx.message.author.mention))
embed.add_field(name = "Server:", value = "{}".format(ctx.message.guild))
embed.add_field(name = "Channel:", value = "<#{}>".format(ctx.message.channel.id))
embed.add_field(name = "Full Command:", value = "{}".format(ctx.message.content))
await output.send(embed = embed)
However, when I attempt to call on that function in a command by using:
await logging(self = self, ctx = ctx, command = "whatever")
I get an error that says Undefined variable: logging. I am new to using cogs and I would appriciate any help you can give.
Related
What could possibly be the course of this exception UnboundLocalError at /group/share/42/ when i try sharing post of another user in a group.The exception trace seems to be on the the first line of the forloop ( new = new_post.video.add(img) ) Here is my view for users to share post
def share_post(request, pk):
original_post = Post.objects.get(pk=pk)
form = ShareForm(request.POST)
if form.is_valid():
new_post = Post(
shared_body = request.POST.get('description'),
description = original_post.description,
username = original_post.username,
date_posted = original_post.date_posted,
shared_on = timezone.now(),
shared_user = request.user)
new_post.save()
for img in original_post.video:
shared = new_post.video.add(img)
shared.save()
return redirect('group:main',original_post.group.pk)
Here is my model Post.
new_post will only be assigned a value if the form is valid, so you should indent the for loop:
def share_post(request, pk):
original_post = Post.objects.get(pk=pk)
form = ShareForm(request.POST)
if form.is_valid():
new_post = Post(
shared_body = request.POST.get('description'),
description = original_post.description,
username = original_post.username,
date_posted = original_post.date_posted,
shared_on = timezone.now(),
shared_user = request.user
)
new_post.save()
for img in original_post.video:
new_post.video.add(img)
return redirect('group:main',original_post.group.pk)
Here's my code:
#bot.command()
#commands.has_permissions(administrator = True)
async def logsave(ctx, amount = None, logName = None):
#Checks if user input an amount, either a number or "all".
if amount == None:
desc = f'**Specify an amount**'
errorEmbed = discord.Embed(title = f'**Log**', description = desc, colour = discord.Color.from_rgb(36, 227, 170))
await ctx.send(embed = errorEmbed)
return
#Checks if user input a name for the log.
if logName == None:
desc = f'**Specify a name.**'
errorEmbed = discord.Embed(title = f'**Log**', description = desc, colour = discord.Color.from_rgb(36, 227, 170))
logMsg = await ctx.send(embed = errorEmbed)
return
#Checks if user input "all"
if amount.lower() == 'all':
isAll = True
else:
isAll = False
#Gets message history
channel = ctx.channel
if isAll:
desc = f'**Started Logging**'
startEmbed = discord.Embed(title = f'**Log**', description = desc, colour = discord.Color.from_rgb(36, 227, 170))
logMsg = await ctx.send(embed = startEmbed)
messages = await channel.history(limit = None, oldest_first = True).flatten()
else:
messages = await channel.history(limit = int(amount), oldest_first = True).flatten()
#Loads previous logs for editing
logsFile = open(f'{currentDirectory}\Saved\logs.json', 'r+')
logsJson = json.load(logsFile)
#Creates new message log in JSON
logCount = logsJson[messages][-1]["count"] + 1
newLog = {
"name": logName,
"creator": ctx.author,
"msgs": [],
"count": logCount
}
logsJson["messageLogs"].append(newLog)
#Stars logging the messages, I'm pretty sure this is where my error is coming from.
for msg in messages:
msgAuthor = msg.author
if msgAuthor.bot:
return
print("done")
msgContent = msg.content
msgAttachments = msg.attachments
msgCreated = msg.created_at
msgWrite = f'\n{msgAuthor} [{msgCreated}]\n{msgContent}'
newMessage = {
"id": msg.id,
"authorname": str(msgAuthor),
"authorid": msgAuthor.id,
"content": msgWrite,
"published": msgCreated,
"attachments": msgAttachments
}
logsJson["messageLogs"][logCount]["msgs"].append(newMessage)
#Edits previous log.
json.dump(logsJson, logsFile)
logsFile.close()
#Ends
logMsg.delete()
desc = f'**Finished Logging**'
endEmbed = discord.Embed(title = f'**Log**', description = desc, colour = discord.Color.from_rgb(36, 227, 170))
await ctx.send(embed = endEmbed)
This is the code for a command that stores messages in a JSON. The problem is that whenever I run this command in discord I get this error:
<discord.ext.commands.context.Context object at 0x000001BB444DC370> Command raised an exception: TypeError: unhashable type: 'list'
I can't seem to figure out what's gone wrong. I've put comments in the code of the command to explain what each part does. I haven't yet figured out if the rest of the code is right so if there's more than one error, feel free to address that as well, right now though I'm just looking for the solution for the particular error above.
TL;DR:
you probably meant to do logsJson["messageLogs"][-1]["count"] + 1
More detail:
When you try to lookup a dictionary with a list value, you get unhashable type: 'list' because dictionaries are just hash tables. You appear to do this here:
logCount = logsJson[messages][-1]["count"] + 1
and you declared messages above this as:
messages = await channel.history(limit = None, oldest_first = True).flatten()
which returns a list of all the messages. So Python can't hash this list and throws the above error. I am guessing you meant to put "messageLogs" in quotes "" as strings are valid keys for a dictionary (they are hashable).
Reproducible example:
x = [1,2,3]
y = {"hello": "world"}
print(y[x])
gives TypeError: unhashable type: 'list'
I created a class that it's created from the YouTube API. It looks like this:
class YouTube:
def __init__(self,name,version,developerKey):
self.service=build(name, version, developerKey)
def get_video_info(self,vid_id):
vid_request = self.service.videos().list(
part = 'snippet,statistics',
id = vid_id,
fields = 'items(kind,id,statistics)')
vid_response = vid_request.execute()
return vid_response
if __name__ == "__main__":
name = 'youtube'
version = 'v3'
api_token='xxxx'
query=YouTube(name,version,api_token)
vid_id='YYYYY_VID_ID'
response = query.get_video_info(vid_id)
pprint(response)
and it works fine, but then I tried the following on the init method:
def __init__(self):
self.name = 'youtube'
self.version = 'v3'
self.developerKey = 'xxxxxxx'
self.service = build(self.name, self.version,self.developerKey)
if __name__ == "__main__":
query = YouTube()
response = query.get_video_info(vid_id)
pprint(response)
I get the following error:
def get_video_info(self,vid_id):
vid_request = self.service.videos().list(
part = 'snippet,statistics',
id=vid_id,
fields= 'items(kind,id,statistics)')
Exception has occurred: AttributeError 'str' object has no attribute 'request'
vid_response = vid_request.execute()
I searched online and I see that this Exception occurs in a variety of situation, and I feel lost? Could someone point me in which direction I should search?
According to this documentation, this is how the build function is defined:
build(serviceName, version, http=None, discoveryServiceUrl=DISCOVERY_URI, developerKey=None, model=None, requestBuilder=HttpRequest, credentials=None, cache_discovery=True, cache=None, client_options=None, adc_cert_path=None, adc_key_path=None, num_retries=1)
Construct a Resource for interacting with an API.
Therefore, you should pass the developer key as a keyword argument in your second snippet:
self.service = build(
self.name,
self.version,
developerKey = self.developerKey
)
In newest update, I have a problem with event: on_guild_channel_update.
I mean, in 1.6.0 it was worked, but in 1.7.0 now have a problem
intents = discord.Intents.all()
client = commands.Bot(command_prefix = get_prefix, intents = intents)
#client.event
async def on_guild_role_update(before, after):
global check_ranga
#e = discord.Embed(color = client.get_user(id_arnoldzika).color, timestamp = datetime.datetime.now(datetime.timezone.utc))
async for author in before.guild.audit_logs(limit = 1, oldest_first = False, action = discord.AuditLogAction.role_update):
member = '{0.user.id}'.format(author)
user = await client.fetch_user(member)
print(user)
#client.event
async def on_guild_channel_update(before, after):
global check_position
check = 0
e = discord.Embed(color = client.get_user(id_arnoldzika).color, timestamp = datetime.datetime.now(datetime.timezone.utc))
async for author in before.guild.audit_logs(limit = 1, oldest_first = False, action = discord.AuditLogAction.channel_update):
print('{0.before} {0.after.type}'.format(author))
member = '{0.user.id}'.format(author)
user = await client.fetch_user(member)
When trigger channel update, I don't get anything, but when trigger role update, correctly print user.
What is the problem with this?
FIXED, fix = await ctx.bot.change_presence.
This is my code for a command that worked with #bot.command() but somehow it doesn't work when I use #commands.command()
bot = commands.Bot(command_prefix = !)
#commands.command()
async def playgame(ctx, game: str=None):
game_count = False
game_list = []
if game:
game_list.append(game)
game_activity = discord.Activity(name=game, type=discord.ActivityType.playing)
activity = discord.Activity(name=".commands", type=discord.ActivityType.listening)
if game_count:
await ctx.send("I'm already playing " + str(game_list[0]))
else:
game_count = True
await ctx.send("ok!")
await bot.change_presence(activity=game_activity) #This calls the error
await asyncio.sleep(60)
await ctx.send("Gotta go, imma stop playing " + str(game_list[0]) + ", bye")
await bot.change_presence(status=discord.Status.dnd, activity=activity)
game_count = False
game_lib = []
else:
msg = "I can't play nothing, use .playgame <game>"
await ctx.send(msg)
def setup(bot):
bot.add_command(playgame)
Probably the problem is just that little thing that you didn't put the command prefix in quotation marks so it is not formatted as string and messes up the whole script.
Solution would be:
bot = commands.Bot(command_prefix = "!")
*Just noticed you already fixed it