Created
February 3, 2023 13:35
-
-
Save a-sakharov/b6bb36b791c698daffca5099c6d565d5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- 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