0

From my understanding I can use this example from the GIPHY docs (https://gyazo.com/1b6c0094162a54fe49029f665badf8df) to open a url but I don't understand it too much. To add onto that, when I run this code I get the error:

discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: module 'urllib' has no attribute 'urlopen'

My question is how can I randomly import a GIF from certain tags once the user types #giphy in a text channel

Here is my current code: (Code got updated)

@bot.command(pass_context = True)
@commands.cooldown(1, 3, commands.BucketType.user)
async def gif(ctx, *, search):
channel = ctx.message.channel
session = aiohttp.ClientSession()

msg = await bot.send_message(channel, "**searching for " + search + "..**")
randomMessage = await bot.send_message(channel, "**showing a random image due to no images found from your search or you just didn't search anything**")

if search == "":
    randomImage = True
    print("random")
    randomMessage
    response = await session.get("https://api.giphy.com/v1/gif/random?api_keyY=4hnrG09EqYcNnv63Sj2gJvmy9ilDPx5&limit=10")
else:
    msg
    print("searching")
    correct_search = search.replace(" ", "+")
    reponse = await session.get("http://api.giphy.com/v1/gifs/search?q=" + correct_search + "&api_key=Y4hnrG09EqYcNnv63Sj2gJvmy9ilDPx5&limit=10")
data = json.loads(await reponse.text())
await session.close()

embed = discord.Embed(
    description = '**showing result for ' + search + '**',
    colour = discord.Colour.blue()
)

gif_choice = random.randint(0,9)
embed.set_image(url=data["data"][gif_choice]["images"]["original"]["url"])
if randomImage:
    await bot.delete_message(randomMessage)
else:
    await bot.delete_message(msg)

await bot.send_message(channel, embed=embed)

Thank you

bb goly
  • 13
  • 1
  • 4
  • Can you try phrasing your question in the form of a question? – mypetlion Nov 09 '18 at 00:17
  • oops I completely forgot to ask the question LOL – bb goly Nov 09 '18 at 00:19
  • What do your import look like? You're probably looking for [`urllib.request.urlopen`](https://docs.python.org/3/library/urllib.request.html#urllib.request.urlopen) – Patrick Haugh Nov 09 '18 at 02:23
  • I have updated my code and fixed my import but i still can't seem to get it to work. It outputs: (file paths) line 96, in giphy await bot.send_message(channel, embed=embed) File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\lib\site-packages\discord\client.py", line 1152, in send_message data = yield from self.http.send_message(channel_id, content, guild_id=guild_id, tts=tts, embed=embed – bb goly Nov 10 '18 at 05:57

1 Answers1

2

The response that the API gives is formatted as json. You need to parse through it to find the url you wish to embed. After it has loaded, it will be a dictionary in python.

The below code is an example of how to do this. It will make a call to the giphy API and return the first 10 results and will randomly select a result as a message.

Note that aiohttp is used as it is asynchronous, meaning it will not block your code. I have also modified the command so that you can search for anything. To match your previous request url, you can use !giphy ryan gosling. If the user does not specify a value for search, then the giphy random endpoint will be used instead.

from discord.ext import commands
import discord
import json
import aiohttp
import random

client = commands.Bot(command_prefix='!')


@client.command(pass_context=True)
async def giphy(ctx, *, search):
    embed = discord.Embed(colour=discord.Colour.blue())
    session = aiohttp.ClientSession()

    if search == '':
        response = await session.get('https://api.giphy.com/v1/gifs/random?api_key=API_KEY_GOES_HERE')
        data = json.loads(await response.text())
        embed.set_image(url=data['data']['images']['original']['url'])
    else:
        search.replace(' ', '+')
        response = await session.get('http://api.giphy.com/v1/gifs/search?q=' + search + '&api_key=API_KEY_GOES_HERE&limit=10')
        data = json.loads(await response.text())
        gif_choice = random.randint(0, 9)
        embed.set_image(url=data['data'][gif_choice]['images']['original']['url'])

    await session.close()

    await client.send_message(embed=embed)

client.run('token')

Also, it seems that discord natively supports giphy. While I was testing, it already made it's own giphy calls. I've tested this using some different characters (!, ~, ') and space and it seems to always work. See below examples.

native giphy discord example: using bot prefix !

native giphy discord example: using ~

native giphy discord example using space

Benjin
  • 3,448
  • 1
  • 10
  • 20
  • Thanks so much! I didn't know that discord had supported giphy like this and to be honest its pretty cool. Since I couldn't find any way to bypass discord automatically trying to change your text to a giphy url whenever you type giphy at the beginning of the sentence i decided to change the command to #gif and now it works perfectly fine! Just one more thing to ask, how can I randomly search for gifs if the user didnt type anything to search? – bb goly Nov 11 '18 at 10:10
  • Sorry for asking a lot of questions, I'm still learning python and this really helped me a lot, but the more I test the command I notice that the gifs that are shown are always the same gifs. Ex. if i search for "terry" the only gif that pops up, no matter how many times i search for terry, is him shouting "My acrylics!". Another thing I noticed is that I cannot add spaces to my searches. Ex. searching up Terry Crews results in an error, how can I replace the space with a _? – bb goly Nov 11 '18 at 10:18
  • I've edited my answer to include a your two scenarios. The random endpoint is used if no search is specified. If it is specified, then 10 results are returned and one is randomly chosen. The command as it is above caters for spaces already. This is done with the * character included in `async def giphy(ctx, *, search):`. Without it you cannot use spaces or you have have to wrap your arguments in quotes, for example `!giphy "Terry Crews"`. Documentation here: https://discordpy.readthedocs.io/en/latest/faq.html#why-do-my-arguments-require-quotes – Benjin Nov 11 '18 at 10:33
  • Thanks the different results work, there's just one thing, i still cant search for terry crews. I have updated my original post to show what I currently have. The following error is what shows up: raise CommandInvokeError(e) from e discord.ext.commands.errors.CommandInvokeError: Command raised an exception: KeyError: 'data' – bb goly Nov 11 '18 at 10:55
  • The url cannot have spaces in it. All spaces must be replaced with `+`. You need something like `search.replace(' ', '+')`. Also, lists start at index 0, not 1. So if you return 10 results, you have index 0 to 9 (which is 10). With `random.randint(1,10)` as you have it, you will never get the first result (index 0) and your code will error if it chooses 10 (no 10 index) – Benjin Nov 11 '18 at 12:22
  • oops looks like I completely forgot to add `search.replace(' ', '+')` and now that part works, but if the user does not put anything after #gif it wont give a random image. The following error appears instead (I also updated the code in my original post to show what I currently have): `embed.set_image(url=data["data"][gif_choice]["images"]["original"]["url"]) IndexError: list index out of range`. – bb goly Nov 11 '18 at 20:49
  • Also if I search for a gif that does not exist it for some reason goes to the random gif if statement and prints the following error: ` raise CommandInvokeError(e) from e discord.ext.commands.errors.CommandInvokeError: Command raised an exception: IndexError: list index out of range` Sorry for asking so much from you, this really helps me a lot – bb goly Nov 11 '18 at 20:52
  • How can I turn the error for a gif that does not exist into the bot saying something like "i can't find anything that matches your search" – bb goly Nov 12 '18 at 00:01
  • The random endpoint does not return more than one response so we do not have to check the index. I've updated my answer so that when using this endpoint, the index is not used. I'm not sure why your search is defaulting to random because if you give it something it should always go to the `else` statement. – Benjin Nov 12 '18 at 06:05
  • Just in case someone is still watching this, I would love to use this example, but the variable "data" is never defined within the code, Benjin – ceiltechbladhm Apr 03 '20 at 15:07
  • 1
    @ceiltechbladhm good catch. My last edit did not handle `data` correctly, it needs to come after `response`, so it has to be in both cases. Also keep in mind that this is for an older version of `discord.py`, the new version does not use `client.send_message` – Benjin Apr 03 '20 at 15:31
  • Hey, this worked out really smoothly. Great example, thanks so much! – ceiltechbladhm Apr 04 '20 at 17:30