Мой бот discord.py, работающий на heroku, продолжает останавливаться - PullRequest
0 голосов
/ 07 августа 2020

У меня очень простой бот c discord.py, размещенный на heroku. Его единственная функция - отправлять сообщение из списка возможных сообщений каждые 24 часа. Он всегда отправляет первое сообщение, а затем останавливается. Я не могу найти никаких ошибок в коде, и когда я уменьшаю тайминги и тестирую его как на моем компьютере, так и на героку, он работает нормально.

Это все в одном файле python с несколько необходимых файлов для heroku и два текстовых документа для сообщений.

Вот основной сценарий:

import discord
import time
import random as rng

clnt = discord.Client()
ch = 0 #channel id
cnt = 0 #amount of minutes on timer
lp = True #i think this is just a leftover variable from another version, i can't find anywhere i used it


@clnt.event
async def on_ready():
    print('ready')


async def ph(): #function to send message
    global ch
    global lp

    qts = open('quotes.txt') #get messages
    qtz = qts.read().splitlines() #put messages in a list
    qts.close() #close file
    
    #if message file is empty, get the list from a backup file and put them into the first file, reseting the messages
    if not qtz:  
        qts2 = open('quoteslog.txt') 
        qtz2 = qts2.read().splitlines()
        qts2.close()

        with open('quotes.txt', 'w') as f:
            for i in qtz2:
                f.write("%s\n" % i)
            f.close()

        qts = open('quotes.txt')
        qtz = qts.read().splitlines()
        qts.close()

    #get random message from list
    x = rng.randint(1, len(qtz))
    x2 = x - 1
    y = qtz[x2]
    qtz.pop(x2)

    open('quotes.txt', 'w').close() #clear the list

    #rewrite the same file without the message sent
    with open('quotes.txt', 'w') as f:
        for i in qtz:
            f.write("%s\n" % i)
        f.close()
    
    #used for messages with new lines
    if y == 'ph1':
        await ch.send("this is for one of the messages, it has new lines so it can't be re-inserted into a txt file")
        await timer()

    elif y == 'ph2':
        await ch.send('same here')
        await timer()

    else:
        #send message to channel and restart the timer
        await ch.send(y)
        await timer()


@clnt.event
async def on_message(m):
    if m.author == clnt.user:
        return

    global ch

    if m.content.startswith('send here'):
        ch = clnt.get_channel(m.channel.id)
        await m.channel.send('ok')

    elif m.content.startswith('start'):
        await timer()


async def timer():  #loops every 60 seconds, 1440 times, or 24hrs
    global lp
    while lp:
        global cnt
        time.sleep(60)
        cnt += 1
        if cnt == 1440:
            cnt = 0 #reset timer and send message
            await ph() 


clnt.run('the discord bot id')

Да, я знаю, что код, вероятно, форматирует мусор, но как насколько я могу судить, он должен работать, а это не так. Я даже не уверен, что это ошибка кода, может также быть проблема с героку, но я понятия не имею.

Если у кого-то есть что-нибудь, что могло бы помочь, это было бы очень признательно!

Ответы [ 2 ]

3 голосов
/ 07 августа 2020

Я рекомендую вам использовать классы Bot и Cog, это будет намного эффективнее, они представлены в discord.py, а имеет декораторы для определения функции цикла . Они находятся в части discord.ext.commands модуля. Вы можете сделать:

from discord.ext import commands, tasks

Я только что ответил на другой пост с примером винтика и функции цикла, вы найдете его здесь . Вот такая же структура, адаптированная к вашему случаю:

# LoopCog.py
from discord.ext import commands, tasks
import random

class LoopCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.test_loop.change_interval(minutes = self.bot.cnt)

    @commands.Cog.listener("on_ready")
    async def on_ready(self):
        self.test_loop.start()

    @tasks.loop(hours=24)
    async def test_loop(self):
        # insert your ph function contents here
        # access the channel id via self.bot.ch

def setup(bot):
    bot.add_cog(LoopCog(bot))
# main.py
from discord.ext import commands

bot = commands.Bot(command_prefix = "!")
bot.ch = 0 
bot.cnt = 0
bot.load_extension("LoopCog")

@bot.event
async def on_ready():
    print("ready")

bot.run(token, reconnect = True)

Я предлагаю вам go посмотреть несколько руководств. Использование класса Client для Bot не является правильным способом для go, вам придется программировать все, что уже есть в Bot, если вы продолжите использовать Client.

Вы Здесь вы найдете документацию по API для Bot , Cog и задач

Касательно heroku , , он, к сожалению, будет перезапускать вашего бота каждые 24 часа , если только вы не go для платного профессионального предложения, которое включает в себя работу 24/7. Он также переведет вашу программу в спящий режим, если она не получит никаких запросов в течение 30 минут.

0 голосов
/ 07 августа 2020

Проблема вашего скрипта в том, что ваша функция цикла никогда не запускается! Это связано с тем, что одна из строк содержит одинарную кавычку, которая преждевременно завершает строку и превращает остальную часть вашего скрипта в гигантскую строку:

 #used for messages with new lines
    if y == 'ph1':
        await ch.send('this is for one of the messages, it has new lines so it can't be 
                       re-inserted into a txt file')
        await timer()

Это легко решить. Либо используйте двойные кавычки:

#used for messages with new lines
    if y == 'ph1':
        await ch.send("this is for one of the messages, it has new lines so it can't be 
                       re-inserted into a txt file")
        await timer()

Или скажите «не могу» вместо «не могу»:

#used for messages with new lines
    if y == 'ph1':
        await ch.send('this is for one of the messages, it has new lines so it cannot be 
                       re-inserted into a txt file')
        await timer()

Обычно всякий раз, когда вы видите, что ваш скрипт становится красным (или становится другим цветом любых строк в вашей среде), если это не строка, вы должны тщательно проверить все свои строки.

...