├── README.md ├── .gitignore ├── tomatych.py ├── tomatych_habitica.py └── tomatych_slack.py /README.md: -------------------------------------------------------------------------------- 1 | # Simple Hackable Pomodoro Timer 2 | 3 | 4 | 5 | Decription 6 | ----------- 7 | 8 | Intended to be hacked and modified to fit your specific vision of how Pomodoro timers should work. Some assembly be required :) 9 | 10 | See recipes: 11 | 12 | * [Score Habitica habits on completed or canceled Pomodoros](http://developer.run/18#habitica) 13 | * [Set Slack to do not disturb mode while Pomodoro is running](http://developer.run/18#dnd) 14 | * [Set Tomato Emoji as Slack status while Pomodoro is running](http://developer.run/18#slack) 15 | * [More...](http://developer.run/18) 16 | 17 | Requirements 18 | ------------ 19 | 20 | 1. On Linux install package `python-tk`, Windows should have it installed with Python 21 | 2. `pip install requests` 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /tomatych.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Simple Hackable Pomodoro Timer 4 | # =============================== 5 | 6 | # 7 | # 8 | # Decription 9 | # ----------- 10 | # 11 | # Intended to be hacked and modified to fit your specific vision of how Pomodoro timers should work. Some assembly may be required :) 12 | # 13 | # See recipes: 14 | # 15 | # * [Score Habitica habits on completed or canceled Pomodoros](http://developer.run/18#habitica) 16 | # * [Set Slack to do not disturb mode while Pomodoro is running](http://developer.run/18#dnd) 17 | # * [Set Tomato Emoji as Slack status while Pomodoro is running](http://developer.run/18#slack) 18 | # * [More...](http://developer.run/18) 19 | 20 | # Author: [Dmitry](http://dmi3.net) [Source](https://github.com/dmi3/bin) 21 | 22 | # Requirements 23 | # ------------ 24 | # 1. On Linux install package `python-tk`, Windows should have it installed with Python 25 | # 2. `pip install requests` 26 | 27 | try: 28 | import Tkinter as tk 29 | except ImportError: 30 | import tkinter as tk 31 | import time 32 | import datetime 33 | import requests 34 | 35 | class App(): 36 | def __init__(self): 37 | self.root = tk.Tk() 38 | self.root.wm_attributes("-topmost", 1) # always on top 39 | self.label = tk.Label(font=("Helvetica Neue", 44)) 40 | self.label.pack() 41 | 42 | self.buttons = tk.Frame(self.root) 43 | self.buttons.pack() 44 | tk.Button(self.buttons, text ="Start", command=lambda: self.start()).pack(side=tk.LEFT) 45 | tk.Button(self.buttons, text ="Cancel", command=lambda: self.cancel()).pack(side=tk.LEFT) 46 | 47 | self.end = time.time() 48 | self.started = False 49 | 50 | self.update_clock() 51 | self.root.mainloop() 52 | 53 | def start(self): 54 | self.started = True 55 | self.end = time.time() + datetime.timedelta(minutes=25).total_seconds() 56 | 57 | print("start") 58 | 59 | def cancel(self): 60 | self.started = False 61 | self.end = time.time() 62 | 63 | print("canceled") 64 | 65 | def complete(self): 66 | self.started = False 67 | 68 | print("completed") 69 | 70 | def update_clock(self): 71 | delta = self.end - time.time() 72 | if delta<0: 73 | self.label.configure(text="00:00", bg="#d9d9d9") 74 | self.root.wm_title("Pomodoro") 75 | if self.started: 76 | self.complete() 77 | else: 78 | time_left = datetime.datetime.fromtimestamp(delta).strftime("%M:%S") 79 | self.root.wm_title("(%s) Pomodoro" % time_left) 80 | self.label.configure(text=time_left, bg="#ca1616") 81 | self.root.after(1000, self.update_clock) 82 | 83 | app=App() 84 | -------------------------------------------------------------------------------- /tomatych_habitica.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Simple Hackable Pomodoro Timer 4 | # =============================== 5 | 6 | # Author: [Dmitry](http://dmi3.net) [Source](https://github.com/dmi3/bin) 7 | 8 | # Requirements 9 | # ------------ 10 | # 1. On Linux and Mac install package `python-tk` 11 | # 2. pip install requests 12 | 13 | try: 14 | import Tkinter as tk 15 | except ImportError: 16 | import tkinter as tk 17 | import time 18 | import datetime 19 | import os 20 | import requests 21 | 22 | API_TOKEN = '' # https://habitica.com/#/options/settings/api 23 | USER_ID = '' # https://habitica.com/#/options/settings/api 24 | TASK_ID = '' 25 | 26 | 27 | class App(): 28 | def __init__(self): 29 | self.root = tk.Tk() 30 | self.root.wm_attributes("-topmost", 1) # always on top 31 | self.root.tk.call('wm', 'iconphoto', self.root._w, tk.PhotoImage(data="R0lGODlhIAAgAOMIAAAAAHkAAJcDALUhBgBlANM/JAChAPFdQv///////////////////////////////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEKAAgALAAAAAAgACAAAASwEMlJq704622BB0ZofKDIUaQ4fuo5pSIcupK8eu1GkkM/EEDC7oMZeny/oBFQNCKDQmNz+FRKX5+D9lDoFlRIsG+55XrFPfSAvPV+RWH42Fh2q9VLN3LPHwj+AnlefYR+gIJdhX2AgUZ6inuMS5CGjH8BmAGTkJaAmZpOnJ0Cn5uKo6SZJCgfSKilRBc8Pq+qsR2ttKOwHlMArru2vTpLVy7FxifIQzQIyzvN0dLTEhEAOw==")) 32 | self.label = tk.Label(font=("Helvetica Neue", 44)) 33 | self.label.pack() 34 | 35 | self.buttons = tk.Frame(self.root) 36 | self.buttons.pack() 37 | tk.Button(self.buttons, text ="Start", command=lambda: self.start()).pack(side=tk.LEFT) 38 | tk.Button(self.buttons, text ="Cancel", command=lambda: self.cancel()).pack(side=tk.LEFT) 39 | 40 | self.end = time.time() 41 | self.started = False 42 | 43 | self.update_clock() 44 | self.root.mainloop() 45 | 46 | def start(self): 47 | self.started = True 48 | self.end = time.time() + datetime.timedelta(minutes=25).total_seconds() 49 | 50 | print("start") 51 | 52 | def cancel(self): 53 | self.started = False 54 | self.end = time.time() 55 | 56 | print("canceled") 57 | requests.post('https://habitica.com/api/v3/tasks/'+TASK_ID+'/score/down', headers={'x-api-key': API_TOKEN, 'x-api-user': USER_ID}) 58 | 59 | def complete(self): 60 | self.started = False 61 | 62 | print("completed") 63 | requests.post('https://habitica.com/api/v3/tasks/'+TASK_ID+'/score/up', headers={'x-api-key': API_TOKEN, 'x-api-user': USER_ID}) 64 | 65 | def update_clock(self): 66 | delta = self.end - time.time() 67 | if delta<0: 68 | self.label.configure(text="00:00", bg="#d9d9d9") 69 | self.root.wm_title("Pomodoro") 70 | if self.started: 71 | self.complete() 72 | else: 73 | time_left = datetime.datetime.fromtimestamp(delta).strftime("%M:%S") 74 | self.root.wm_title("(%s) Pomodoro" % time_left) 75 | self.label.configure(text=time_left, bg="#ca1616") 76 | self.root.after(1000, self.update_clock) 77 | 78 | app=App() 79 | -------------------------------------------------------------------------------- /tomatych_slack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Simple Hackable Pomodoro Timer 4 | # =============================== 5 | 6 | # Some assembly may be required :) 7 | # [Read More](http://developer.run/18) 8 | 9 | # Author: [Dmitry](http://dmi3.net) [Source](https://github.com/dmi3/bin) 10 | 11 | # Requirements 12 | # ------------ 13 | # 1. On Linux and Mac install package `python-tk` 14 | # 2. pip install requests 15 | 16 | try: 17 | import Tkinter as tk 18 | except ImportError: 19 | import tkinter as tk 20 | import time 21 | import datetime 22 | import os 23 | import requests 24 | 25 | xoxp_TOKEN = '' # get one at https://api.slack.com/custom-integrations/legacy-tokens 26 | 27 | class App(): 28 | def __init__(self): 29 | self.root = tk.Tk() 30 | self.root.wm_attributes("-topmost", 1) # always on top 31 | self.root.tk.call('wm', 'iconphoto', self.root._w, tk.PhotoImage(data="R0lGODlhIAAgAOMIAAAAAHkAAJcDALUhBgBlANM/JAChAPFdQv///////////////////////////////yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEKAAgALAAAAAAgACAAAASwEMlJq704622BB0ZofKDIUaQ4fuo5pSIcupK8eu1GkkM/EEDC7oMZeny/oBFQNCKDQmNz+FRKX5+D9lDoFlRIsG+55XrFPfSAvPV+RWH42Fh2q9VLN3LPHwj+AnlefYR+gIJdhX2AgUZ6inuMS5CGjH8BmAGTkJaAmZpOnJ0Cn5uKo6SZJCgfSKilRBc8Pq+qsR2ttKOwHlMArru2vTpLVy7FxifIQzQIyzvN0dLTEhEAOw==")) 32 | self.label = tk.Label(font=("Helvetica Neue", 44)) 33 | self.label.pack() 34 | 35 | self.buttons = tk.Frame(self.root) 36 | self.buttons.pack() 37 | tk.Button(self.buttons, text ="Start", command=lambda: self.start()).pack(side=tk.LEFT) 38 | tk.Button(self.buttons, text ="Cancel", command=lambda: self.cancel()).pack(side=tk.LEFT) 39 | 40 | self.end = time.time() 41 | self.started = False 42 | 43 | self.update_clock() 44 | self.root.mainloop() 45 | 46 | def start(self): 47 | self.started = True 48 | self.end = time.time() + datetime.timedelta(minutes=25).total_seconds() 49 | 50 | print("start") 51 | 52 | requests.get('https://slack.com/api/dnd.setSnooze', params=(('token', xoxp_TOKEN), ('num_minutes', '25'))) 53 | requests.post('https://slack.com/api/users.profile.set', params=(('token', xoxp_TOKEN), ('name','status_emoji'), ('value', ':tomato:'))) 54 | 55 | def cancel(self): 56 | self.started = False 57 | self.end = time.time() 58 | 59 | print("canceled") 60 | 61 | requests.get('https://slack.com/api/dnd.endSnooze', params=(('token', xoxp_TOKEN),)) 62 | requests.post('https://slack.com/api/users.profile.set', params=(('token', xoxp_TOKEN), ('name','status_emoji'))) 63 | 64 | def complete(self): 65 | self.started = False 66 | 67 | print("completed") 68 | 69 | requests.get('https://slack.com/api/dnd.endSnooze', params=(('token', xoxp_TOKEN),)) 70 | requests.post('https://slack.com/api/users.profile.set', params=(('token', xoxp_TOKEN), ('name','status_emoji'))) 71 | 72 | def update_clock(self): 73 | delta = self.end - time.time() 74 | if delta<0: 75 | self.label.configure(text="00:00", bg="#d9d9d9") 76 | self.root.wm_title("Pomodoro") 77 | if self.started: 78 | self.complete() 79 | else: 80 | time_left = datetime.datetime.fromtimestamp(delta).strftime("%M:%S") 81 | self.root.wm_title("(%s) Pomodoro" % time_left) 82 | self.label.configure(text=time_left, bg="#ca1616") 83 | self.root.after(1000, self.update_clock) 84 | 85 | app=App() 86 | --------------------------------------------------------------------------------