discord.py asyncio coroutine - функция частично запущена - PullRequest
0 голосов
/ 09 мая 2020

Я пишу бота Discord с помощью discord.py и пытаюсь реализовать систему для покупки акций на python 3.6, поскольку python3 .7 + имеет asyncio.run(func()).

import discord
import asyncio
import os
import random
import time
import math

client = discord.Client()

# contains coin information including balance, stock price, number of stocks, etc
with open('coins.conf', 'r') as f:
    for line in f.readlines():
        exec(line)

def save_all():
    with open('coins.conf', 'w') as f:
        f.write('coins = '+repr(coins))

random.seed(os.urandom(32))
searchusers = []
bank_cooldown = {}
bans['global'] = False

@client.event
async def on_ready():
    '''Notification on ready.'''
    print('Logged in! Bot running.')
    await client.change_presence(activity=discord.Game(name='/help'))

@client.event
async def on_member_join(user):
    '''Direct message the rules on member join.'''
    await user.create_dm()
    await user.dm_channel.send(f'Hi **{user.name}**, welcome to the server! Be sure to read the rules to stay out of trouble. Have a great time!')

def getcoins(uid):
    '''Get the amount of coins, if nonexistent set to 0.'''
    try:
        return coins[uid][0]
    except Exception:
        coins[uid] = [0, time.time()+1, time.time()+1, 0, 320, time.time()+600, 0]
        return 0

def mention_to_uid(mention):
    '''Extract the UID from a mention (exclude first two char and last char)'''
    uid = mention[2:-1]
    if uid[0] == '!':
        uid = uid[1:]
    return uid

def setcoins(uid, value):
    '''Set the amount of coins someone has.'''
    try:
        coins[uid][0] = value
    except Exception:
        coins[uid] = [value, time.time()+1, time.time()+1, 0, 320, time.time()+600, 0]

@client.event
async def on_message(message):
    '''Main bot code running on message.'''

    #############################
    # some initialization stuff #
    #############################

    if message.content.startswith('/'):
        user = message.author.id
        name = message.author.display_name
        text = message.content[1:].strip()
        command = text.split(' ')[0]
        subcommand = text.split(' ')[1:]

        ######################
        # other bot commands #
        ######################

        if command == 'stocks':
            if len(subcommand) < 2:
                await message.channel.send('Missing arguments! `/stocks [buy | sell] <amount>` or `/stocks help [info | price]`')
            elif subcommand[0] == 'help':
                if subcommand[1] == 'info':
                    msg = 'Invest in bot stocks! Use `/stocks help price` to find the current price per share.'
                    msg += '\nEvery 7-15 minutes, the stock price will change. It will decrease or increase by a little bit.'
                    msg += '\nStocks will more than likely output profit, but it is very random.'
                    msg += '\nEvery share bought increases the price by 1 and every share sold decreases the price by 1.'
                    await message.channel.send(msg)
                elif subcommand[1] in ('price', 'amount', 'cost'):
                    await message.channel.send(f"The current stock price is **{getcoins('stock')}**. Get them while you can!")
            elif subcommand[0] == 'buy':
                amount = int(subcommand[1])
                if amount < 0:
                    await message.channel.send('lol dummy. Positive number dude.')
                else:
                    cost = (amount * getcoins('stock')) + (amount**2 - amount)//2 # price including increases
                    if getcoins(user) < cost:
                        await message.channel.send(f"You don't have enough coins to buy that many shares! Try `/balance`.\n[Debug] {cost}")
                    else:
                        coins[user][6] += amount # coins[user][6] => number of stocks user has
                        setcoins(user, getcoins(user)-cost)
                        setcoins('stock', getcoins('stock')+amount)
                        await message.channel.send(f'You bought {amount} shares for {cost} coins.')
            elif subcommand[0] == 'sell':
                amount = int(subcommand[1])
                if amount < 0:
                    await message.channel.send('lol dummy. Positive number dude.')
                else:
                    sell = (amount * getcoins('stock')) - (amount**2 - amount)//2 # price including decreases
                    if coins[user][6] < amount:
                        await message.channel.send(f"You don't have enough shares!")
                    else:
                        coins[user][6] -= amount
                        setcoins(user, getcoins(user)+sell)
                        setcoins('stock', getcoins('stock')-amount)
                        await message.channel.send(f'You sold {amount} shares for {sell} coins.')
            else:
                await message.channel.send('Invalid arguments! `/stocks [buy | sell] <amount>` or `/stocks help [info | price]`')

            ######################
            # other bot commands #
            ######################


##################################
# this stuff is the main problem #
##################################

async def main():
    '''Bot code.'''
    await client.start('Nj*********************************************************')
    while True:
        await asyncio.sleep(random.randint(420,900))
        ## I'm certain anything below this doesn't run ##
        change = random.choice([ *1*[-50], *4*[-8], *5*[-7], *6*[-6], *7*[-5], *8*[-4], *9*[-3], *10*[-2], *10*[-1],
            *10*[0], *10*[1], *10*[2], *10*[3], *9*[4], *8*[5], *7*[6], *6*[7], *5*[8], *4*[9], *3*[10], *2*[12], *1*[15]
            ])
        setcoins('stock', getcoins('stock')+change)
        if getcoins('stock') < 15:
            setcoins('stock', 15)

        setcoins('jackpot', getcoins('jackpot')+random.randint(10, 20))




asyncio.get_event_loop().run_until_complete(main())

Выполняется только половина функции.

Строка await client.start() не должна быть блокирующим вызовом и в любом случае ожидается. Даже после ожидания 20 минут (максимум 15 минут) вторая часть строки l oop - change = random.choice и все, что ниже, не запускается.

Я думаю, проблема в вызове client.start блокирует, но из документации (https://discordpy.readthedocs.io/en/latest/api.html#discord .Client.start )

await start(*args, **kwargs) Эта функция является сопрограммой. Сокращенная сопрограмма для login () + connect ().

Вызывает ошибку TypeError - был получен неожиданный аргумент ключевого слова. команда start - это сопрограмма.

Я попытался уменьшить время asyncio.sleep до 10 секунд и даже полностью удалить его. Цена акций и сумма джекпота билетов, которые предполагается изменить, не меняются.

...