Короче говоря, я новичок в API и асинхронном программировании. Я пытаюсь создать бота Discord, который публикует статус вашей платформы Steam на экране состояния бота (по крайней мере, на данный момент), но я получаю эту ошибку, когда запускаю Discord_Bot.py. Не знаю, что это значит и почему, но это касается меня, потому что ошибка, кажется, найдена в одном из файлов Discord (который я не написал).
Сначала я получил эту ошибку сразу после запуска Discord_Bot.py:
Ignoring exception in on_ready
Traceback (most recent call last):
File "C:\Users\Mira\Anaconda3\lib\site-packages\discord\client.py", line 307, in _run_event
yield from getattr(self, event)(*args, **kwargs)
TypeError: on_ready() missing 1 required positional argument: 'self'
File "C:\Users\USER\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)
File "C:\Users\USER\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/USER/Documents/GitHub/Discord_Steam_Interface/Discord_Bot.py", line 83, in <module>
b.run_the_bot()
File "C:/Users/USER/Documents/GitHub/Discord_Steam_Interface/Discord_Bot.py", line 75, in run_the_bot
self.client.run(self.__BOT_TOKEN)
File "C:\Users\USER\Anaconda3\lib\site-packages\discord\client.py", line 534, in run
self.loop.close()
File "C:\Users\USER\Anaconda3\lib\asyncio\selector_events.py", line 107, in close
raise RuntimeError("Cannot close a running event loop")
RuntimeError: Cannot close a running event loop
Затем я применил патч nest_asyncio, который можно найти здесь: https://github.com/erdewit/nest_asyncio
Это, похоже, решило проблему, так как я больше не получил 'RuntimeError: Не удается закрытьОшибка запуска цикла обработки событий сразу после запуска скрипта. Однако сейчас я замечаю, что, если я оставлю его на 5 минут, он появится снова. Кроме того, ошибка ниже продолжает появляться сразу после запуска скрипта. Я в пути над своей головой, помогите?
Ignoring exception in on_ready
Traceback (most recent call last):
File "C:\Users\USER\Anaconda3\lib\site-packages\discord\client.py", line 307, in _run_event
yield from getattr(self, event)(*args, **kwargs)
TypeError: on_ready() missing 1 required positional argument: 'self'
Вот Discord_Bot.py: (мой файл)
import time
import win32gui
import psutil
import subprocess
import discord
import asyncio
import get_steam_info
import nest_asyncio
# Applies a patch which allows asyncio's event loop to be nested.
nest_asyncio.apply()
class Bot_handler():
# Define the Client object for this session.
client = discord.Client()
def __init__(self, program_name, steam_id, api_key, bot_token):
self.program_name = program_name
self.process = self.program_name + '.exe'
self.__program_running = self.get_program_running(self.process)
self.__STEAM_ID = STEAM_ID
self.__API_KEY = API_KEY
self.__BOT_TOKEN = BOT_TOKEN
def get_program_running(self, process_str):
'''Determine whether the specified process_str is running.'''
if process_str in (process.name() for process in psutil.process_iter()):
self.__program_running = True
print(self.program_name,"is currently running.")
else:
self.__program_running = False
print(self.program_name,"is not currently running.")
return self.__program_running
@client.event
async def on_ready(self):
'''Called automatically when client is done preparing data from Discord.
Schedules coroutine on_ready using Task client.loop.create_task.'''
self.__client.loop.create_task(self.status_task())
print('Logged in as')
print(self.__client.user.name)
print(self.__client.user.id)
print('------')
async def status_task(self):
while True:
if self.__program_running:
self.__player_info = get_steam_info.get_player_info(self.__API_KEY, self.__STEAM_ID)
self.__player_status = get_steam_info.get_player_status(self.__player_info)
self.__ingame = get_steam_info.get_ingame_name(self.__player_info)
if self.__ingame:
await self.__client.change_presence(status = discord.Status.online, game = discord.Game(name = str(self.__ingame)), afk=False)
await asyncio.sleep(3)
else:
await self.__client.change_presence(status = discord.Status.dnd, game = discord.Game(name = 'nothing at the moment'))
await asyncio.sleep(3)
else:
self.get_active_window()
def get_active_window(self):
'''Return the title of the active window as a string.'''
self.__active_window = win32gui.GetWindowText(win32gui.GetForegroundWindow())
return self.__active_window
def run_the_bot(self):
# Activates the bot.
self.client.run(self.__BOT_TOKEN)
PROGRAM_NAME = 'Steam'
# Real values are present in the code
STEAM_ID = 'ZZZZZZZZZ'
API_KEY = 'XXXXXXXX'
BOT_TOKEN = 'YYYYYYYYYY'
b = Bot_handler(PROGRAM_NAME, STEAM_ID, API_KEY, BOT_TOKEN)
b.run_the_bot()
get_steam_info.py (мойфайл)
import requests
class Info_handler():
'''Keep track of a player's information in real time.'''
def __init__(self, steam_ID, API_key):
self.__steam_ID = steam_ID
self.__API_key = API_key
self.__API_url = 'https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=' \
+ self.__API_key +'&steamids=' + self.__steam_ID
self.statuslist = {0: 'offline', 1: 'online', 3: 'dnd', 4: 'idle', 5: 'idle', 6: 'online', 7: 'online'}
# call status
# profile_url = 'https://steamcommunity.com/profiles/' + steam_ID
self.__player_info = self.get_player_info()
self.__player_status = self.get_player_status(self.__player_info)
def get_player_info(self):
'''Returns a dict containing Steam information for one player using the
Steam API. Requires the desired player's user ID and a valid API key.'''
self.response = requests.get(self.__API_url)
if self.response.status_code != 200:
raise Exception('Request unsuccessful; returned code ' + str(self.response.status_code) \
+ ': ' + str(requests.status_codes._codes[self.response.status_code][0]))
else:
print('Success! API responded to call.')
self.__player_info = self.response.json()['response']['players'][0]
return self.__player_info
def get_player_status(self, player_info_dict):
'''Returns the player's Steam status as a Discord status type.
STEAM STATUS | STEAM STATE | DISCORD STATUS
'Offline' | 0 | 'Offline'
'Online' | 1 | 'Online'
'Busy' | 2 | 'dnd'
'Away' | 3 | 'Idle'
'Snooze' | 4 | 'Idle'
'Looking to trade' | 5 | 'Online'
'Looking to play' | 6 | 'Online'
'''
self.__steam_state = player_info_dict['personastate']
self.__player_status = self.statuslist[self.__steam_state]
return self.__player_status
# Is it better to use 'self.__steam_state' since when this variable will never
# called outside the function? Or shall I use simply 'steam_state?'
def get_ingame_name(self, player_info_dict):
'''Returns the name of the Steam game player is playing.
If player is logged into Steam, but not currently playing anything,
return False.'''
self.__player_name = player_info_dict['personaname']
try:
self.__game = player_info_dict['gameextrainfo']
print('Player ',self.__player_name,' is playing ',self.__game,'.',sep='')
return self.__game
except KeyError:
print('Player',self.__player_name,'is not currently in a game.')
return False
def get_player_name(self):
return self.__player_name
steam_ID = 'ZZZZZZZZZ'
API_key = 'XXXXXXXX'
instance = Info_handler(steam_ID, API_key)
info = instance.get_player_info()
print(info)
status = instance.get_player_status(info)
print(status)
game = instance.get_ingame_name(info)
print(game)