-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
executable file
·196 lines (152 loc) · 5.94 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#!/usr/bin/env python3
import time
from config import bot_token
import datetime
from aiogram import Bot, types
from aiogram.utils import executor
from aiogram.utils.markdown import text
from aiogram.dispatcher import Dispatcher
from aiogram.dispatcher import FSMContext
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.types.input_file import InputFile
from aiogram.dispatcher.filters import Text
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from pathlib import Path
from matplotlib import pyplot as plt
import db_handler as db
import functions as funcs
import classes
storage = MemoryStorage()
bot = Bot(bot_token)
dp = Dispatcher(bot, storage=storage)
# States
class Form(StatesGroup):
weight = State() # Will be represented in storage as 'Form:weight'
weight_past = State()
graph_n_days = State()
# You can use state '*' if you need to handle all states
@dp.message_handler(state='*', commands='cancel')
@dp.message_handler(Text(equals='cancel', ignore_case=True), state='*')
async def cancel_handler(message: types.Message, state: FSMContext):
''' Allow user to cancel any action '''
current_state = await state.get_state()
if current_state is None:
return
await state.finish()
await message.reply('Cancelled.', reply_markup=types.ReplyKeyboardRemove())
@dp.message_handler(commands="start")
async def show_help(message: types.Message):
''' Show help msg at start '''
await message.answer(funcs.get_help_msg())
@dp.message_handler(commands="add_record")
async def do_add_record(message: types.Message):
''' handle 'add_record' command '''
await Form.weight.set()
line = 'Input your weight and an optional comment, valid examples:\n' \
'*78.3*\n' \
'or this:\n' \
'*40.1 oops, i need to eat!*'
await message.answer(line, parse_mode='Markdown')
@dp.message_handler(commands='add_skipped_record')
async def add_skipped_record(message: types.Message):
''' handle 'add_record' command '''
await Form.weight_past.set()
line = 'Input date, your weight and an optional comment, valid examples:\n' \
'*13.02.2023 78.3*\n' \
'or this:\n' \
'*13.02.2023 40.1 oops, i need to eat!*'
await message.answer(line, parse_mode='Markdown')
@dp.message_handler(commands="del_record_1_day")
async def del_rec_1_hour(message: types.Message):
key = InlineKeyboardMarkup()
try:
last_rec = db.get_last_n_recs(message.from_user.id, 1)[0]
except Exception:
await message.answer('Record not found')
return
key.row(InlineKeyboardButton(text='I want to delete this record', callback_data='del_rec_' + str(message.from_user.id)))
line = 'Last record:\n\n'
line += funcs.make_rec_readable(last_rec)
await message.answer(text=line, reply_markup=key)
@dp.callback_query_handler(lambda c: c.data)
async def callback_inline(call: types.CallbackQuery):
call_data_arr = call.data.split('_')
if call_data_arr[0] == 'del' and call_data_arr[1] == 'rec':
await call.answer(db.del_last_rec_1_day(call_data_arr[2]))
@dp.message_handler(commands="show_week")
async def show_week(message: types.Message):
week_graph_path = funcs.get_graph(message.from_user.id, 7)
week_graph = InputFile(week_graph_path)
await message.answer_photo(photo=week_graph)
@dp.message_handler(commands='show_month')
async def show_month(message: types.Message):
month_graph_path = funcs.get_graph(message.from_user.id, 30)
month_graph = InputFile(month_graph_path)
await message.answer_photo(photo=month_graph)
@dp.message_handler(commands='show_n_days')
async def show_n_days(message: types.Message):
await Form.graph_n_days.set()
await message.answer('Input number of days you need like so:\n40')
@dp.message_handler(state=Form.graph_n_days)
async def send_graph(message: types.Message, state: FSMContext):
days_num = message.text
try:
days_num = int(days_num)
custom_graph_path = funcs.get_graph(message.from_user.id, days_num)
custom_graph = InputFile(custom_graph_path)
await message.answer_photo(photo=custom_graph)
except Exception:
line = 'ERROR: number of days is not an integer:\n' + days_num
await message.answer(line)
await state.finish()
@dp.message_handler(state=Form.weight)
async def get_weight_from_user(message: types.Message, state: FSMContext):
weight = message.text.split(' ')[0:1]
weight = ''.join(weight)
weight = weight.replace( ',', '.' )
comment = message.text.split(' ')[1:]
comment = ' '.join(comment)
await message.reply(add_record(message.from_user.id, weight, comment))
await state.finish()
@dp.message_handler(state=Form.weight_past)
async def get_weight_from_user_past(message: types.Message, state: FSMContext):
date = message.text.split(' ')[0:1]
date = ' '.join(date)
weight = message.text.split(' ')[1:2]
weight = ''.join(weight)
weight = weight.replace( ',', '.' )
comment = message.text.split(' ')[2:]
comment = ' '.join(comment)
await message.reply(add_record(message.from_user.id, weight, comment, date))
await state.finish()
def add_record(user_id, weight, comment, date=None):
try:
weight = float(weight)
except Exception:
line = 'ERROR: weight is not a number:\n' + weight
return line
new_rec = classes.Record()
new_rec.set_user_id(user_id)
if date != None:
try:
date_ts = float(time.mktime(datetime.datetime.strptime(date, "%d.%m.%Y").timetuple()))
except Exception as e:
return e
print('date_ts', date_ts)
new_rec.set_date_ts(round(date_ts, 0))
else:
new_rec.set_date_ts(round(time.time(), 0))
new_rec.set_weight(round(weight, 2))
new_rec.set_comment(comment)
result = db.add_rec(new_rec)
if result == new_rec:
line = 'Record added:\n\n'
line += funcs.make_rec_readable(new_rec)
else:
line = result
return line
if __name__ == '__main__':
db_started = db.start()
print('Start db:', db_started)
executor.start_polling(dp)