2

Update: After few uncessful attempts to explain the problem, completely rewrote the question:

How to execute a function on startup?

from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'API'

bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler()
async def echo(message: types.Message):
  await message.answer(message.text)

async def notify_message() # THIS FUNCTION
  # await bot.sendMessage(chat.id, 'Bot Started')
  await print('Hello World')

if __name__ == '__main__':
   notifty_message() # doesn't work
   executor.start_polling(dp, skip_updates=True)

Tried without success::

if __name__ == '__main__':
  dp.loop.create_task(notify_message()) # Function to execute
  executor.start_polling(dp, skip_updates=True)

AttributeError: 'NoneType' object has no attribute 'create_task'

if __name__ == '__main__':
  loop = asyncio.get_event_loop()
  loop.create_task(notify_message()) # Function to execute
  executor.start_polling(dp, skip_updates=True)

TypeError: object NoneType can't be used in 'await' expression

Mike S.
  • 205
  • 2
  • 12

6 Answers6

1

you can call aiogram.executor.start(dispatcher, future) to run an async function (future)

from aiogram import Bot, Dispatcher, executor

bot = Bot(token='your_api_token')
dp = Dispatcher(bot)

async def notify_message() # THIS FUNCTION
  # await bot.sendMessage(chat.id, 'Bot Started')
  await print('Hello World')

@dp.message_handler()
async def echo(message: types.Message):
  await message.answer(message.text)

if __name__ == '__main__':
    executor.start(dp, notify_message())
    executor.start_polling(dp, skip_updates=True)
ipu_
  • 11
  • 2
1

I apologize in advance if my English is bad. I don't speak it well)))

It is much easier than you thought)

Aiogram has built-in tool for this: on_startup. You may create a function that takes a single argument: Dispatcher, and acts the way you need it to. In your case it would like something like this:

from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'API'

bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler()
async def echo(message: types.Message):
  await message.answer(message.text)

async def notify_message(dp: Dispatcher) # THIS FUNCTION
  print('Hello World')

if __name__ == '__main__':
   executor.start_polling(dp, skip_updates=True, on_startup=notify_message)

Also you can await your function like this:

from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'API'

bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler()
async def echo(message: types.Message):
  await message.answer(message.text)

async def notify_message() # THIS FUNCTION
  # await print('Hello World')
  print('Hello, world') # you shouldn't await the print fucntion, because it isn't async.

if __name__ == '__main__':
   await notifty_message()
   executor.start_polling(dp, skip_updates=True)

OR, you can make it not async and simply ask it like this:

from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'API'

bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler()
async def echo(message: types.Message):
  await message.answer(message.text)

def notify_message() # THIS FUNCTION
  print('Hello, world')

if __name__ == '__main__':
   notifty_message()
   executor.start_polling(dp, skip_updates=True)

Choose variant which you like more) If I were you, I would choose the first, because it is, as I said before, built-in desicion by aiogram, and you can use some functions as if bot works, such as for examle send admins that bot is turned on.

P.S.

You can find more information in aiogram docs

Something like this answer should have been)

TimKostenok
  • 52
  • 11
0

If you want to iniate a dialogue, it's impossible, telegram doesn't allow bots to send first message. But if you want to save your users ids, you can make a database or just a txt file and write there any new user id. You will be able to send to all of them messages by inputing id from database instead of chat.id

ZloiGoroh
  • 411
  • 4
  • 11
  • Hi, thank you for the feedback. Sorry for the confusion. Scenario, Bot already initiated, and working. and upon restart, I wanted to send a message to already existing chat id. (eg, my chat.id) – Mike S. Jul 31 '21 at 10:59
0

I give you an example of how to send a message without using message.answer just use:

@dp.message_handler()
async def echo(message: types.Message):
    await bot.send_message(message.chat.id, message.text)

I don't understand why you need to print ('The bot is running') When running "aiogram" it tells you that the bot was started

2021-06-01 09:31:42,729:INFO:Bot: YourBot [@YourBot]
2021-06-01 09:31:42,729:WARNING:Updates were skipped successfully.
2021-06-01 09:31:42,729:INFO:Start polling.
  • Thanks for the answer. @dp.message_handler() waits for the user to input a message. Therefore i wanted something that it sends already to existing chat a message. I can see in the logs that the bot is running, but it was just an example, to send notification over the telegram. In the example i just # the main message, and was asking how to execute a function, though it would be easier. – Mike S. Aug 07 '21 at 18:54
0

It was much simpler than expected. facepalm
Working Solution:

from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'API'
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

@dp.message_handler()
async def echo(message: types.Message):
   await bot.send_message(message.chat.id, message.text)

def test_hi():
   print("Hello World")

if __name__ == '__main__':
   test_hi()
   executor.start_polling(dp, skip_updates=True)
Mike S.
  • 205
  • 2
  • 12
0

The second approach was correct, but asyncio event loop was not initialised. So, if it was important to call async function beside a bot, you would do:

from asyncio import get_event_loop
from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'API'

bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot=bot, loop=get_event_loop())  # Initialising event loop for the dispatcher

async def notify_message():
    print('Hello World')

if __name__ == '__main__':
    dp.loop.create_task(notify_message())  # Providing awaitable as an argument
    executor.start_polling(dp, skip_updates=True)
Airat K
  • 55
  • 1
  • 1
  • 10