Repository: interactions-py/interactions.py

Issue:
[BUG] inconsistencies and bugs in tasks
### Describe the bug.

In the latest 5.x, tasks don't work properly.
Basically, there are 2 things that are going wrong:

1. If the task is not started immediately after the bot turns on, it will silently keep adding calls to the list. When the task is started, like maybe 10 seconds later, the past 10 tasks that were supposed to happen but weren't started, will be called with no delay between each other and all immediately, which should not happen in the first place.
2. When the task is stopped, it isn't really stopped. Sure, the code doesn't get executed, but when you restart the task, it may run many times with no delay, which would probably break whatever code you wanted to run at an interval.

### List the steps.

Here is my code to reproduce this bug:
```py
import interactions
from asyncio import sleep
from time import time

bot = interactions.Client()
increment = 0
last_call = time()


@interactions.Task.create(interactions.IntervalTrigger(seconds=1))
async def my_task():
    global increment, last_call
    increment += 1
    print(increment, time() - last_call)
    last_call = time()


@interactions.listen()
async def on_startup():
    print("Bot is ready!")


@interactions.slash_command("test_task")
async def test_task(ctx: interactions.SlashContext):
    await ctx.send("Watch the console for inconsistencies")
    print("# starting task")
    my_task.start()
    print("# waiting 10 seconds")
    await sleep(10)
    print("# stopping task")
    my_task.stop()
    print("# waiting 10 seconds")
    await sleep(10)
    print("# starting task again")
    my_task.start()
    print("# waiting 5 seconds")
    await sleep(5)
    print("# stopping task again")
    my_task.stop()


bot.start("token")
```

### What you expected.

When the task is started in the command, it should only call it once, not many times because it wasn't started immediately.
Whenever the task is stopped, it should actually stop, instead of having a backlog of callbacks that get called immediately when you start it again.

### What you saw.

Here is the output of the above program:
```py
Bot is ready!
# starting task
# waiting 10 seconds
1 9.517415285110474
2 0.0
3 0.0
4 0.0
5 0.0
6 0.0010004043579101562
7 0.0010004043579101562
8 0.0
9 0.0
10 0.4808993339538574
11 0.9963068962097168
12 1.0010671615600586
13 0.9928460121154785
14 0.9866108894348145
15 1.0092473030090332
16 0.9739875793457031
17 0.9932007789611816
18 0.9856703281402588
19 0.9991569519042969
# stopping task
# waiting 10 seconds
# starting task again
# waiting 5 seconds
20 10.533191442489624
21 0.0009999275207519531
22 0.0
23 0.0
24 0.0010006427764892578
25 0.0
26 0.0
27 0.0
28 0.00400233268737793
29 0.0
30 0.464735746383667
31 0.9912123680114746
32 1.0092799663543701
33 0.9981844425201416
34 0.9897663593292236
# stopping task again
```


### What version of the library did you use?

unstable

### Version specification

5.x

### Code of Conduct

- [X] I agree to follow the contribution requirements.


Discussion:

Resolving patch:
diff --git a/interactions/models/internal/tasks/task.py b/interactions/models/internal/tasks/task.py
--- a/interactions/models/internal/tasks/task.py
+++ b/interactions/models/internal/tasks/task.py
@@ -111,6 +111,7 @@ async def _task_loop(self) -> None:
     def start(self) -> None:
         """Start this task."""
         try:
+            self.trigger.reschedule()
             self._stop.clear()
             self.task = asyncio.create_task(self._task_loop())
         except RuntimeError:
diff --git a/interactions/models/internal/tasks/triggers.py b/interactions/models/internal/tasks/triggers.py
--- a/interactions/models/internal/tasks/triggers.py
+++ b/interactions/models/internal/tasks/triggers.py
@@ -15,6 +15,10 @@ def __new__(cls, *args, **kwargs) -> "BaseTrigger":
     def __or__(self, other: "BaseTrigger") -> "OrTrigger":
         return OrTrigger(self, other)
 
+    def reschedule(self) -> None:
+        """Update the last call time to now"""
+        self.last_call_time = datetime.now()
+
     @abstractmethod
     def next_fire(self) -> datetime | None:
         """


Test patch: