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
|
import datetime
import signal
import sys
import logging
from os import getenv
from typing import Union
from googleapiclient.discovery import Resource
from telegram.ext import Updater, CommandHandler, CallbackContext
from telegram import Update
from telegram.ext.jobqueue import Job
from sheets_client import (
authenticate_sheets,
fetch_sheet_data,
update_sheet_last_done_column,
)
from data_parser import (
filter_only_this_week,
process_rows,
updated_last_done_datestamps,
)
from functools import partial
chats_mem_cache = {}
ALLOWED_USER_IDS = [
int(id) for id in getenv("TELEGRAM_USER_IDS", "").split(",") if len(id) > 0
]
def _signal_handler(sig, frame):
print("You pressed Ctrl+C!")
updater = frame.f_locals["updater"]
for chat_id in chats_mem_cache.keys():
updater.bot.send_message(chat_id=chat_id, text="HommaBot-palvelin sammutettu!")
updater.stop()
sys.exit(0)
def _callback_alarm(context: CallbackContext, sheets_service: Resource):
chat_id: int = context.job.context
logging.info(f"Authenticating and fetching data from Sheets...")
rows = fetch_sheet_data(sheets_service)
logging.info(f"Processing data...")
processed_rows = process_rows(rows)
this_weeks_rows = filter_only_this_week(processed_rows)
logging.info(f"Sending sheet data to chat id {chat_id}...")
if len(this_weeks_rows) > 0:
message = "Tällä viikolla tehtävät hommat:\n" + "\n".join(
f"{task.name} ({task.interval})" for task in this_weeks_rows
)
else:
message = "Tällä viikolla ei toistuvia hommia! 🎉 "
context.bot.send_message(chat_id=chat_id, text=message)
new_datestamps = updated_last_done_datestamps(processed_rows)
update_sheet_last_done_column(sheets_service, new_datestamps)
def _callback_timer(update: Update, context: CallbackContext, sheets_service: Resource):
chat_id = update.message.chat_id
user_id = update.message.from_user.id
if user_id not in ALLOWED_USER_IDS:
logging.info(f"User {user_id} is not allowed to start timer.")
update.message.reply_text(
"Käyttäjälläsi ei ole oikeuksia startata HommaBottia."
)
return
logging.info(f"Starting timer in chat id {chat_id}...")
update.message.reply_text(
"HommaBot startattu. Uusia hommapäivityksiä viikon välein."
)
job = context.job_queue.run_repeating(
partial(_callback_alarm, sheets_service=sheets_service),
datetime.timedelta(weeks=1),
1, # run once immediately after 1 sec
name="callback_alarm",
context=chat_id,
)
chats_mem_cache[chat_id] = job
def _stop_timer(update: Update, context: CallbackContext):
chat_id = update.message.chat_id
user_id = update.message.from_user.id
if chat_id not in chats_mem_cache:
return
if user_id not in ALLOWED_USER_IDS:
logging.info(f"User {user_id} is not allowed to stop timer.")
update.message.reply_text(
"Käyttäjälläsi ei ole oikeuksia pysäyttää HommaBottia."
)
return
logging.info(f"Stopping timer in chat id {chat_id}...")
update.message.reply_text("HommaBot pysäytetty!")
job: Job = chats_mem_cache[chat_id]
job.schedule_removal()
del chats_mem_cache[chat_id]
def run_telegram():
sheets_service = authenticate_sheets()
tg_token = getenv("TELEGRAM_TOKEN")
logging.info("Creating Telegram bot object...")
updater = Updater(tg_token)
logging.info("Registering Telegram bot /start handler...")
updater.dispatcher.add_handler(
CommandHandler(
"start",
partial(_callback_timer, sheets_service=sheets_service),
pass_job_queue=True,
)
)
logging.info("Registering Telegram bot /stop handler...")
updater.dispatcher.add_handler(
CommandHandler("stop", _stop_timer, pass_job_queue=True)
)
logging.info("Starting Telegram bot (HommaBot)...")
updater.start_polling()
logging.info("Registering SIGINT handler...")
signal.signal(signal.SIGINT, _signal_handler)
logging.info("Bot started successfully. Pausing main thread... (this is expected)")
signal.pause()
|