Skip to content

Instantly share code, notes, and snippets.

@a-sakharov
Created February 3, 2023 13:35
Show Gist options
  • Select an option

  • Save a-sakharov/b6bb36b791c698daffca5099c6d565d5 to your computer and use it in GitHub Desktop.

Select an option

Save a-sakharov/b6bb36b791c698daffca5099c6d565d5 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
import asyncio
import datetime
import sys
from pyrogram import Client
import random
from num2words import *
# Тут надо выставить параметры соответствующие своим (https://my.telegram.org/apps). Я свои на всякий случай заменю заглушками
API_ID = 0
API_HASH = "000000000000000000000000000000000"
class PillsSchedule:
name = "" # Название препарата. Гроприносин, например
per_time_amount = 0 # Сколько пьется за раз. Например, 2
per_day_times = 0 # Сколько раз в день пьется. Например, 1
total_count = 0 # Сколько единиц всего надо принять. Не сколько раз, а сколько единиц
already_consumed = 0 # Сколько уже принято в единицах. Опять же, в единицах, а не в разах
per_day_first_offset = 0 # Задержка в минутах от полуночи до первой дозы
per_day_subsequent_offset = 0 # Задержка в минутах перед последующими приемами относительно предыдущего приема
days_period = 0 # сколько дней пропускается между приемами
days_offset = 0 # Задержка в днях перед первых приемом
course_started = None # datetime первого приема?
def __init__(self, name, per_time_amount=1, per_day_times=1, total_count=1, already_consumed=0, per_day_first_offset=60*8, per_day_subsequent_offset=60*4, days_period=1, days_offset=0):
self.name = name
self.per_time_amount = per_time_amount
self.per_day_times = per_day_times
self.total_count = total_count
self.already_consumed = already_consumed
self.per_day_first_offset = per_day_first_offset
self.per_day_subsequent_offset = per_day_subsequent_offset
self.days_period = days_period
self.days_offset = days_offset
class OneTimePills:
name = ""
count = 0
total_consumed = 0
total_count = 0
def __init__(self, name, count, total_consumed, total_count):
self.name = name
self.count = count
self.total_consumed = total_consumed
self.total_count = total_count
def get_right_noun(count):
if count == 1:
return "штука"
elif count >=2 and count <=4:
return "штуки"
else:
return "штук"
def datetime_to_day_start(date):
return datetime.datetime.combine(date.date(), datetime.time(0))
def pills_array_to_time_text(pills_array, start_of_admission=datetime.datetime.today()+datetime.timedelta(days=1)): # default start_of_admission is tomorrow
# 1. строим массив со всеми приемами (название, количество и время)
# 2. объединяем те приемы, что имеют одно время, и генерируем текст
if start_of_admission.second != 0 or start_of_admission.microsecond != 0:
start_of_admission -= datetime.timedelta(seconds=start_of_admission.second, microseconds=start_of_admission.microsecond)
times = dict()
for pill in pills_array:
if pill.days_offset:
time_offset = datetime_to_day_start(start_of_admission) + datetime.timedelta(days=pill.days_offset)
else:
time_offset = start_of_admission
while pill.already_consumed < pill.total_count:
for in_day_index in range(pill.per_day_times):
consumption_time_in_day_offset = pill.per_day_first_offset + in_day_index * pill.per_day_subsequent_offset
consumption_datetime = datetime_to_day_start(time_offset) + datetime.timedelta(minutes=consumption_time_in_day_offset)
if time_offset <= consumption_datetime and pill.already_consumed < pill.total_count:
pill.already_consumed += pill.per_time_amount
if consumption_datetime not in times:
times[consumption_datetime] = list()
times[consumption_datetime].append(OneTimePills(pill.name, pill.per_time_amount, pill.already_consumed, pill.total_count))
# print("💊 Consumed {0} pills of {1} at {2} ({3}/{4})".format(pill.per_time_amount, pill.name, consumption_datetime, pill.already_consumed, pill.total_count))
if pill.days_period:
time_offset = datetime_to_day_start(time_offset) + datetime.timedelta(days=pill.days_period)
else:
time_offset = datetime_to_day_start(time_offset) + datetime.timedelta(days=1)
result = dict()
lang_ru_n2w = lang_RU.Num2Word_RU()
for time in times:
if time.hour < 12:
text = "Доброе утро!\n"
elif time.hour > 19:
text = ""
else:
text = "Привет\n"
text += "Сейчас тебе нужно принять следующее:\n"
for pill in times[time]:
text += ("💊 {0}: {1} {2}. Это будет {3} из {4}, или {5:.1f}%\n".format(pill.name, lang_ru_n2w._int2word(pill.count, True), get_right_noun(pill.count), pill.total_consumed, pill.total_count, pill.total_consumed/pill.total_count*100.))
# Возможные поздравления.
# Первый элемент - вес, выше - больше вероятность что выпадет
# Второй элемент - само поздравление
# Можно менять и удалять как нравится
trailing_text_setup = [
[3, ""],
[3, "Выздоравливай!"],
[3, "Ты справишься!"],
[3, "Скоро будешь здоровой!"],
[2, "Хмели сумели и ты сможешь!"],
[2, "Выпей таблетку, чтобы показать какая ты особенная"],
[2, "Ради Барсика!"],
[3, "За Маму"],
[3, "За Папу"],
[1, "За Юлю"],
[1, "За Настю"],
]
trailing_text_final = []
for item in trailing_text_setup:
trailing_text_final = [*trailing_text_final, *(item[0] * [item[1]])]
random.shuffle(trailing_text_final)
training_text = trailing_text_final[random.randint(0, len(trailing_text_final)-1)]
text += training_text
if time.hour > 19:
if text[-1] != '\n':
text += '\n'
text += "Спокойной ночи!"
result[time] = text
return result
async def create_notifications(to, messages):
async with Client("my_account", API_ID, API_HASH) as app:
for date in messages:
if date >= datetime.datetime.now():
pass
await app.send_message(chat_id=to, text=messages[date], schedule_date=date)
def print_messages(messages):
for date in messages:
print(date)
print(messages[date])
print()
print()
# Тут настраиваются таблетосы
pills = [
PillsSchedule("Гроприносин", per_time_amount=2, per_day_times=3, total_count=168, already_consumed=0, per_day_first_offset=60*8, per_day_subsequent_offset=60*6, days_period=0, days_offset=0),
PillsSchedule("Юнидокс", per_time_amount=1, per_day_times=2, total_count=20, already_consumed=0, per_day_first_offset=60*8, per_day_subsequent_offset=60*12, days_period=0, days_offset=0),
PillsSchedule("Флуконазол 150мг", per_time_amount=1, per_day_times=1, total_count=2, already_consumed=0, per_day_first_offset=60*8, per_day_subsequent_offset=0, days_period=5, days_offset=5),
PillsSchedule("Метрамикон форте", per_time_amount=1, per_day_times=1, total_count=7, already_consumed=0, per_day_first_offset=60*20, per_day_subsequent_offset=0, days_period=0, days_offset=0),
PillsSchedule("Джес Плюс", per_time_amount=1, per_day_times=1, total_count=56, already_consumed=0, per_day_first_offset=60*8, per_day_subsequent_offset=0, days_period=0, days_offset=14),
]
time_text = pills_array_to_time_text(pills, start_of_admission=datetime.datetime(2023, 1, 20, 18, 0, 0))
print_messages(time_text)
# Отправка. Для теста отправляем сами себе, иначе надо изменить 'me' на имя пользователя
asyncio.run(create_notifications(to="me", messages=time_text))
print("Done!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment