如何使用 Python Discord Bot 将 GIF 发送到 Discord 频道

How do I send a GIF to a Discord channel using a Python Discord Bot

当用户输入命令“!gif”(他们想要的 gif 在哪里)时,我希望机器人 return 该名称的 gif。

我正在尝试的代码基于来自 Tenor 的 API,但我不介意使用任何其他站点来获取 gif。我目前的代码不起作用,我对如何去做这件事有点无能为力。

注意:我将此作为个人项目进行。我不介意你给我答案,但如果可以,请解释你为什么要这样做。

到目前为止,这是我的代码:

import discord
import requests
import json

from constants import (TenorToken, DiscordToken)

client = discord.Client()
embedColour = 0xff0000

#Retrieves GIF from site
def getGIF(searchTerm):
    response = requests.get("https://g.tenor.com/v1/search?q=%s&key=%s&limit=1" %(searchTerm, TenorToken))
    gif = json.loads(response.content)
    print(gif)

@client.event
async def on_ready():
    print(f"{client.user}"[:-5] + " is now Online!")

@client.event
async def on_message(message):
    if (message.author == client.user):
        return

    if (message.content.lower().startswith(f"{CommandKey}gif")):
        getGIF(message.content.lower()[5:]) #Collects word after !gif

client.run(DiscordToken)

感谢您的帮助!

我检查了你的代码,Tensor 不发送 GIF 数据,只发送图像的 url。

此代码在第一个结果中为 gif 提供了 url`

def get_gif(searchTerm):  # PEP8: lower_case_names for functions

    response = requests.get("https://g.tenor.com/v1/search?q={}&key={}&limit=1".format(searchTerm, TenorToken))

    data = response.json()  # `requests` doesn't need `json.loads()`
         
    return data['results'][0]['media'][0]['gif']['url']

我通过手动挖掘 JSON 并创建此代码来获得它

# see urls for all GIFs

for result in data['results']:
    print('- result -')
    #print(result)
    
    for media in result['media']:
        print('- media -')
        #print(media)
        #print(media['gif'])
        print('url:', media['gif']['url'])

当我收到 url 时,我可以使用 Embed 发送 url 并且 discord 将下载它并显示 - 我不必下载它。

if (message.content.lower().startswith(f"{CommandKey}gif")):

    gif_url = get_gif(message.content.lower()[5:]) #Collects word after !gif
    
    embed = discord.Embed()
    embed.set_image(url=gif_url)

    await message.channel.send(embed=embed)

完整的工作代码

import discord
import requests

from constants import (TenorToken, DiscordToken)

#import os
#DiscordToken = os.getenv('DISCORD_TOKEN')
#TenorToken = os.getenv('TENOR_TOKEN')

client = discord.Client()

embedColour = 0xff0000
CommandKey = '!'

# --- functions ---

#Retrieves GIF from site
def get_gif(searchTerm):  # PEP8: lower_case_names for functions
    response = requests.get("https://g.tenor.com/v1/search?q={}&key={}&limit=1".format(searchTerm, TenorToken))
    data = response.json()
    
    ''' 
    # see urls for all GIFs
    
    for result in data['results']:
        print('- result -')
        #print(result)
        
        for media in result['media']:
            print('- media -')
            print(media)
            print(media['gif'])
            print('url:', media['gif']['url'])
    '''
         
    return data['results'][0]['media'][0]['gif']['url']
    

@client.event
async def on_ready():
    print(f"{client.user}"[:-5] + " is now Online!")

@client.event
async def on_message(message):
    if message.author == client.user:  # `if/else` doesn't need `()`
        return

    if message.content.lower().startswith(f"{CommandKey}gif"):
        gif_url = get_gif(message.content.lower()[5:]) #Collects word after !gif
        
        embed = discord.Embed()
        embed.set_image(url=gif_url)
        await message.channel.send(embed=embed)

# --- main ---

client.run(DiscordToken)

编辑:

与将 gif 下载到本地计算机内存(使用 io.BytesIO)并作为普通文件发送相同。

import io

@client.event
async def on_message(message):
    if (message.author == client.user):
        return

    if (message.content.lower().startswith(f"{CommandKey}gif")):
        gif_url = get_gif(message.content.lower()[5:]) #Collects word after !gif
        # download image from url
        response = requests.get(gif_url) 
        
        # put it in file-like object in memory
        file_like_object = io.BytesIO(response.content)

        #file_name = 'image.gif'
        file_name = gif_url.split('/')[-1]
        
        # send it as normal file
        # it needs filename with extension `.gif` to display it as GIF image
        await message.channel.send(file=discord.File(file_like_object, filename=file_name))

显示需要较长的时间,因为它必须将其获取到本地计算机,然后将其发送到互联网。

它可以用于使用 pillow, wand, gizeh, detect faces/peoples/object with opencv, genererate videos with moviepy 等编辑图像(即添加文本、更改颜色、绘制图形)等


顺便说一句:

在回答问题 时,我使用 pillow 向图像添加元素。但它是静态图像,而不是需要更多工作的动画 GIF(每帧单独)