Skip to content

Commit 281da8b

Browse files
Merge pull request #3 from KingWaffleIII/dev
v1.2.0
2 parents 6e4cf79 + 4306f66 commit 281da8b

File tree

13 files changed

+201
-104
lines changed

13 files changed

+201
-104
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ config.json
66
*.zip
77
dist/
88
.idea
9-
*.bak
9+
*.bak
10+
.vscode/

AntiProcrastinator.spec

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# -*- mode: python ; coding: utf-8 -*-
22

33
main = Analysis(
4-
['main.py'],
4+
["main.py"],
55
pathex=[],
66
binaries=[],
7-
datas=[('annoying.mp3', '.')],
7+
datas=[("annoying.mp3", "."), ("icon.png", "."), ("icon2.png", ".")],
88
hiddenimports=[],
99
hookspath=[],
1010
hooksconfig={},
@@ -19,14 +19,14 @@ main_exe = EXE(
1919
main.binaries,
2020
main.datas,
2121
[],
22-
name='AntiProcrastinator',
22+
name="AntiProcrastinator",
2323
debug=False,
2424
bootloader_ignore_signals=False,
2525
strip=False,
2626
upx=True,
2727
upx_exclude=[],
2828
runtime_tmpdir=None,
29-
console=True,
29+
console=False,
3030
disable_windowed_traceback=False,
3131
argv_emulation=False,
3232
target_arch=None,
@@ -35,9 +35,9 @@ main_exe = EXE(
3535
)
3636

3737
configurator = Analysis(
38-
['configurator.py'],
38+
["configurator.py"],
3939
pathex=[],
40-
binaries=[],
40+
binaries=[("icon.png", "."), ("icon2.png", ".")],
4141
datas=[],
4242
hiddenimports=[],
4343
hookspath=[],
@@ -53,7 +53,7 @@ configurator_exe = EXE(
5353
configurator.binaries,
5454
configurator.datas,
5555
[],
56-
name='Configurator',
56+
name="Configurator",
5757
debug=False,
5858
bootloader_ignore_signals=False,
5959
strip=False,

README.md

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
11
# AntiProcrastinator
22

3+
## Windows only, cross-platform support WIP
4+
35
A Python script that yells at you for doing things you shouldn't be. Yes, I was procrastinating when I made this.
46

57
Features:
68

7-
- Immediately yells at you on launch
8-
- Monitors the focused window and yells at you if you're procrastinating
9-
- Matches blacklisted strings in the window name
10-
- Pauses any media you're playing to yell at you
11-
- Regularly reminds you how close your deadline is
12-
- Customisable insults
13-
- Realtime config changes (no need to restart the program)
14-
- Completely customisable actions (e.g. play a sound, print to console, etc.)
15-
- Extending the project and adding your own actions is very simple by simply extending `action.Action`.
16-
- You can make actions from emailing someone to shutting down your computer.
9+
- Immediately yells at you on launch
10+
- Monitors the focused window and yells at you if you're procrastinating
11+
- Matches blacklisted strings in the window name
12+
- Pauses any media you're playing to yell at you
13+
- Regularly reminds you how close your deadline is
14+
- Customisable insults
15+
- Realtime config changes (no need to restart the program)
16+
- Completely customisable actions (e.g. play a sound, print to console, etc.)
17+
- Extending the project and adding your own actions is very simple by simply extending `action.Action`.
18+
- You can make actions from emailing someone to shutting down your computer.
19+
- Break feature with customisable duration
1720

1821
## Usage:
1922

20-
- [Download the latest release](https://github.com/KingWaffleIII/AntiProcrastinator/releases) and run once.
21-
- Run `configurator.exe` to edit the config.
22-
- Run `AntiProcrastinator.exe`!
23-
24-
- **Available actions:**
25-
- `Sleep`
26-
- `Say`
27-
- `Exit`
28-
- `Playsound`
29-
- `Closewindow`
30-
- `Print`
31-
32-
- **Wildcards:**
33-
- `{deadline}` -> `get_deadline()`
34-
- `{insult}` -> `get_insult()`
35-
- `{timer_diff}` -> `get_timer_diff_in_text()`
36-
- `{window}` -> `window`
37-
38-
- (recommended but optional) Add to Task Scheduler or equivalent (put the executable in `shell:common startup` in Windows Explorer) to run on startup
23+
- [Download the latest release](https://github.com/KingWaffleIII/AntiProcrastinator/releases) and run once.
24+
- Run `configurator.exe` to edit the config.
25+
- Run `AntiProcrastinator.exe`!
26+
27+
- **Available actions:**
28+
29+
- `Sleep`
30+
- `Say`
31+
- `Exit`
32+
- `Playsound`
33+
- `Closewindow`
34+
- `Notify`
35+
36+
- **Wildcards:**
37+
- `{deadline}` -> `get_deadline()`
38+
- `{insult}` -> `get_insult()`
39+
- `{timer_diff}` -> `get_timer_diff_in_text()`
40+
- `{window}` -> `window`
41+
42+
- (recommended but optional) Add to Task Scheduler or equivalent (put the executable in `shell:common startup` in Windows Explorer) to run on startup
3943

4044
This runs the script on startup and in the background.
4145
Enable this if you use Task Scheduler else TTS will not work:
@@ -44,4 +48,4 @@ Enable this if you use Task Scheduler else TTS will not work:
4448

4549
You can run the Python script from cloning or the executable from releases, **but make sure to have `config.json` in the same directory**.
4650

47-
Note: when using `actions.PlaySound`, remember to add the sound files to `AntiProcrastinator.spec` if using Pyinstaller.
51+
Note: when using `actions.PlaySound`, remember to add the sound files to `AntiProcrastinator.spec` if using Pyinstaller.

actions/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
from .playsound import Playsound as Playsound
77
from .say import Say as Say
88
from .sleep import Sleep as Sleep
9-
from .print import Print as Print
9+
from .notify import Notify as Notify

actions/defaults.py

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# actions.Exit
1010
# actions.Playsound
1111
# actions.Closewindow
12-
# actions.Print
12+
# actions.Notify
1313

1414
# Wildcards:
1515
# {deadline} -> get_deadline()
@@ -21,45 +21,72 @@
2121
# Avoid using Python, rather use the available functions in util.functions.
2222
# If you want to use something not implemented, you can add it to util/functions.py.
2323

24-
OnStartupActionSet = actions.Actionset([
25-
actions.Say(
26-
text="Good luck bro, the deadline has passed.",
27-
pause_media=True,
28-
condition_func="lambda: util.functions.has_deadline_passed()",
29-
),
30-
actions.Exit(
31-
condition_func="lambda: util.functions.has_deadline_passed()",
32-
),
33-
actions.Say(
34-
text="{deadline}Time to lock in!",
35-
pause_media=True,
36-
condition_func=None,
37-
),
38-
])
24+
OnStartupActionSet = actions.Actionset(
25+
[
26+
actions.Say(
27+
text="Good luck bro, the deadline has passed.",
28+
pause_media=True,
29+
condition_func="lambda: util.functions.has_deadline_passed()",
30+
),
31+
actions.Exit(
32+
condition_func="lambda: util.functions.has_deadline_passed()",
33+
),
34+
actions.Say(
35+
text="{deadline}Time to lock in!",
36+
pause_media=True,
37+
condition_func=None,
38+
),
39+
]
40+
)
3941

40-
OnProcrastinationActionSet = actions.Actionset([
41-
actions.Say(
42-
text="{deadline}{insult}", pause_media=True, condition_func="lambda: not util.functions.check_timer_elapsed_time(60)"
43-
),
44-
actions.Sleep(
45-
sleep_time=60,
46-
condition_func="lambda: not util.functions.check_timer_elapsed_time(60)",
47-
),
48-
actions.Say(
49-
text="Nah you're finished, you've been procrastinating for {timer_diff}! {insult}",
50-
pause_media=True,
51-
condition_func=None,
52-
),
53-
actions.Playsound(
54-
file_path=r"{runtime_dir}\annoying.mp3",
55-
),
56-
])
42+
OnProcrastinationActionSet = actions.Actionset(
43+
[
44+
actions.Say(
45+
text="{deadline}{insult}",
46+
pause_media=True,
47+
condition_func="lambda: not util.functions.check_timer_elapsed_time(60)",
48+
),
49+
actions.Sleep(
50+
sleep_time=60,
51+
condition_func="lambda: not util.functions.check_timer_elapsed_time(60)",
52+
),
53+
actions.Say(
54+
text="Nah you're finished, you've been procrastinating for {timer_diff}! {insult}",
55+
pause_media=True,
56+
condition_func=None,
57+
),
58+
actions.Playsound(
59+
file_path=r"{runtime_dir}\annoying.mp3",
60+
),
61+
]
62+
)
5763

58-
AfterProcrastinationActionSet = actions.Actionset([
59-
actions.Print(text="[{timestamp}] You were procrastinating for {timer_diff} on {window}!"),
60-
actions.Say(
61-
text="You retard, you were procrastinating for {timer_diff}! {insult}",
62-
pause_media=True,
63-
condition_func=None,
64-
),
65-
])
64+
AfterProcrastinationActionSet = actions.Actionset(
65+
[
66+
actions.Notify(
67+
# text="[{timestamp}] You were procrastinating for {timer_diff} on {window}!"
68+
text="You were procrastinating for {timer_diff} on {window}!"
69+
),
70+
actions.Say(
71+
text="You retard, you were procrastinating for {timer_diff}! {insult}",
72+
pause_media=True,
73+
condition_func=None,
74+
),
75+
]
76+
)
77+
78+
BreakActionSet = actions.Actionset(
79+
[
80+
actions.Say(
81+
text="Well done, you can relax for a bit.",
82+
pause_media=True,
83+
condition_func=None,
84+
),
85+
actions.Sleep(600),
86+
actions.Say(
87+
text="Break's over! Get back to work, those As aren't gonna earn themselves.",
88+
pause_media=True,
89+
condition_func=None,
90+
),
91+
]
92+
)
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
from util.functions import icon
2+
13
from .action import Action
24

35

4-
class Print(Action):
6+
class Notify(Action):
57
def __init__(self, text: str, condition_func: str = None):
68
"""
7-
Creates an action that prints to the console.
8-
:param text: the text to print.
9+
Creates an action that sends a desktop notification.
10+
:param text: the text to send.
911
:param condition_func: the condition to check before executing the action, as a string cast lambda function.
1012
"""
1113
super().__init__(condition_func)
@@ -20,20 +22,23 @@ def to_json(self):
2022
import util
2123

2224
if self.condition_func is not None:
23-
condition_func_str = util.functions.deconstruct_condition_function(self.raw_condition_func)
25+
condition_func_str = util.functions.deconstruct_condition_function(
26+
self.raw_condition_func
27+
)
2428
condition_func = {
2529
"function": condition_func_str[0],
2630
"inverse": condition_func_str[1],
27-
"args": condition_func_str[2]
31+
"args": condition_func_str[2],
2832
}
2933
else:
3034
condition_func = None
31-
return {"action": "Print", "condition_func": condition_func, "text": self.text}
35+
return {"action": "Notify", "condition_func": condition_func, "text": self.text}
3236

3337
async def execute(self):
3438
if not await super().execute():
3539
return False
3640

3741
import util
42+
3843
text = util.functions.replace_wildcards(self.text)
39-
print(text)
44+
icon.notify(text)

configurator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def action_set_menu():
1919
"On Startup": util.config.config["on_startup"],
2020
"On Procrastination": util.config.config["on_procrastination"],
2121
"After Procrastination": util.config.config["after_procrastination"],
22+
"Break": util.config.config["break"],
2223
}
2324

2425
choice = inquirer.select(
@@ -27,6 +28,7 @@ def action_set_menu():
2728
"On Startup",
2829
"On Procrastination",
2930
"After Procrastination",
31+
"Break",
3032
"Deadlines",
3133
"Blacklist",
3234
"Whitelist",

icon.png

17.6 KB
Loading

icon2.png

1.82 MB
Loading

main.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,20 @@
33
import multiprocessing
44
import multiprocessing.popen_spawn_win32 as forking
55
import os
6-
import time
76
import sys
7+
import threading
8+
import time
9+
810
import win32gui
911

1012
import actions
1113
import util
1214

1315
if not util.config.config_exists("config.json"):
14-
print("Config file not found. Please run the configurator first.")
15-
sys.exit(-1)
16+
# print("Config file not found. Please run the configurator first.")
17+
# sys.exit(-1)
18+
util.config.create_config("config.json")
19+
print("Config file created!")
1620

1721
try:
1822
util.config.load_config("config.json")
@@ -68,8 +72,10 @@ async def watch():
6872
proc = None
6973
while True:
7074
window = win32gui.GetWindowText(win32gui.GetForegroundWindow())
71-
if window != "" and any(
72-
x in window.lower() and x not in util.config.config["whitelist"] for x in util.config.config["blacklist"]
75+
if (
76+
window
77+
and any(x in window.lower() for x in util.config.config["blacklist"])
78+
and not any(x in window.lower() for x in util.config.config["whitelist"])
7379
):
7480
if proc is None or not proc.is_alive():
7581
util.functions.start_timer()
@@ -88,7 +94,12 @@ async def watch():
8894
time.sleep(1)
8995

9096

91-
if __name__ == "__main__":
92-
multiprocessing.freeze_support()
97+
def run():
9398
asyncio.run(startup())
9499
asyncio.run(watch())
100+
101+
102+
if __name__ == "__main__":
103+
multiprocessing.freeze_support()
104+
threading.Thread(target=run).start()
105+
util.functions.icon.run()

0 commit comments

Comments
 (0)