" token
165 | return n_tokens
166 |
167 | def _count_tokens_for_gpt(self, prompt, answer, model="text-davinci-003"):
168 | encoding = tiktoken.encoding_for_model(model)
169 | n_tokens = len(encoding.encode(prompt)) + len(encoding.encode(answer)) + 1
170 | return n_tokens
171 |
172 |
173 | async def transcribe_audio(audio_file):
174 | r = await openai.Audio.atranscribe("whisper-1", audio_file)
175 | return r["text"]
--------------------------------------------------------------------------------
/bot/database.py:
--------------------------------------------------------------------------------
1 | from typing import Optional, Any
2 |
3 | import pymongo
4 | import uuid
5 | from datetime import datetime
6 |
7 | from bot import config
8 |
9 |
10 | class Database:
11 | def __init__(self):
12 | self.client = pymongo.MongoClient(config.mongodb_uri)
13 | self.db = self.client["chatgpt_telegram_bot"]
14 |
15 | self.user_collection = self.db["user"]
16 | self.dialog_collection = self.db["dialog"]
17 | self.payment_collection = self.db["payment"]
18 | self.newsletter_collection = self.db["newsletter"]
19 |
20 | def check_if_user_exists(self, user_id: int, raise_exception: bool = False):
21 | if self.user_collection.count_documents({"_id": user_id}) > 0:
22 | return True
23 | else:
24 | if raise_exception:
25 | raise ValueError(f"User {user_id} does not exist")
26 | else:
27 | return False
28 |
29 | def check_if_payment_exists(self, payment_id: int, raise_exception: bool = False):
30 | if self.payment_collection.count_documents({"_id": payment_id}) > 0:
31 | return True
32 | else:
33 | if raise_exception:
34 | raise ValueError(f"Payment {payment_id} does not exist")
35 | else:
36 | return False
37 |
38 | def check_if_newsletter_exists(self, newsletter_id: int, raise_exception: bool = False):
39 | if self.newsletter_collection.count_documents({"_id": newsletter_id}) > 0:
40 | return True
41 | else:
42 | if raise_exception:
43 | raise ValueError(f"Newsletter {newsletter_id} does not exist")
44 | else:
45 | return False
46 |
47 | def add_new_user(
48 | self,
49 | user_id: int,
50 | chat_id: int,
51 | initial_token_balance: int = 5000,
52 | username: str = "",
53 | first_name: str = "",
54 | last_name: str = "",
55 | ):
56 | user_dict = {
57 | "_id": user_id,
58 | "chat_id": chat_id,
59 |
60 | "username": username,
61 | "first_name": first_name,
62 | "last_name": last_name,
63 |
64 | "last_interaction": datetime.now(),
65 | "first_seen": datetime.now(),
66 |
67 | "current_dialog_id": None,
68 | "current_chat_mode": "assistant",
69 |
70 | "n_used_tokens": 0,
71 | "token_balance": initial_token_balance
72 | }
73 |
74 | if not self.check_if_user_exists(user_id):
75 | self.user_collection.insert_one(user_dict)
76 |
77 | def start_new_dialog(self, user_id: int):
78 | self.check_if_user_exists(user_id, raise_exception=True)
79 |
80 | dialog_id = str(uuid.uuid4())
81 | dialog_dict = {
82 | "_id": dialog_id,
83 | "user_id": user_id,
84 | "chat_mode": self.get_user_attribute(user_id, "current_chat_mode"),
85 | "start_time": datetime.now(),
86 | "messages": []
87 | }
88 |
89 | # add new dialog
90 | self.dialog_collection.insert_one(dialog_dict)
91 |
92 | # update user's current dialog
93 | self.user_collection.update_one(
94 | {"_id": user_id},
95 | {"$set": {"current_dialog_id": dialog_id}}
96 | )
97 |
98 | return dialog_id
99 |
100 | def get_user_attribute(self, user_id: int, key: str):
101 | self.check_if_user_exists(user_id, raise_exception=True)
102 | user_dict = self.user_collection.find_one({"_id": user_id})
103 |
104 | if key not in user_dict:
105 | raise ValueError(f"User {user_id} does not have a value for {key}")
106 |
107 | return user_dict[key]
108 |
109 | def set_user_attribute(self, user_id: int, key: str, value: Any):
110 | self.check_if_user_exists(user_id, raise_exception=True)
111 | self.user_collection.update_one({"_id": user_id}, {"$set": {key: value}})
112 |
113 | def check_if_user_attribute_exists(self, user_id: int, key: str):
114 | self.check_if_user_exists(user_id, raise_exception=True)
115 | user_dict = self.user_collection.find_one({"_id": user_id})
116 | return key in user_dict
117 |
118 | def get_dialog_messages(self, user_id: int, dialog_id: Optional[str] = None):
119 | self.check_if_user_exists(user_id, raise_exception=True)
120 |
121 | if dialog_id is None:
122 | dialog_id = self.get_user_attribute(user_id, "current_dialog_id")
123 | if dialog_id is None:
124 | return []
125 |
126 | dialog_dict = self.dialog_collection.find_one({"_id": dialog_id, "user_id": user_id})
127 | return dialog_dict["messages"]
128 |
129 | def set_dialog_messages(self, user_id: int, dialog_messages: list, dialog_id: Optional[str] = None):
130 | self.check_if_user_exists(user_id, raise_exception=True)
131 |
132 | if dialog_id is None:
133 | dialog_id = self.get_user_attribute(user_id, "current_dialog_id")
134 |
135 | self.dialog_collection.update_one(
136 | {"_id": dialog_id, "user_id": user_id},
137 | {"$set": {"messages": dialog_messages}}
138 | )
139 |
140 | def count_documents_in_collection(self, collection_name: str):
141 | return self.db[collection_name].count_documents({})
142 |
143 | def get_new_unique_payment_id(self):
144 | if self.payment_collection.count_documents({}) == 0:
145 | payment_id = 0
146 | else:
147 | payment_id = 1 + self.payment_collection.find_one(sort=[("_id", pymongo.DESCENDING)])["_id"]
148 |
149 | return payment_id
150 |
151 | def add_new_payment(
152 | self,
153 | payment_id: int,
154 | payment_method: str, # like: cryptomus, cards
155 | payment_method_type: str, # like: cryptomus, telegram_payments
156 | product_key: str,
157 | user_id: int,
158 | amount: float,
159 | currency: str,
160 | status: str,
161 | invoice_url: str,
162 | n_tokens_to_add: int,
163 | expired_at: datetime
164 | ):
165 | payment_dict = {
166 | "_id": payment_id,
167 | "payment_method": payment_method,
168 | "payment_method_type": payment_method_type,
169 | "product_key": product_key,
170 | "user_id": user_id,
171 | "amount": amount,
172 | "currency": currency,
173 | "status": status,
174 | "invoice_url": invoice_url,
175 | "n_tokens_to_add": n_tokens_to_add,
176 | "expired_at": expired_at,
177 | "created_at": datetime.now(),
178 | "are_tokens_added": False
179 | }
180 |
181 | self.payment_collection.insert_one(payment_dict)
182 |
183 | def get_payment_attribute(self, payment_id: int, key: str):
184 | self.check_if_payment_exists(payment_id, raise_exception=True)
185 | payment_dict = self.payment_collection.find_one({"_id": payment_id})
186 |
187 | if key not in payment_dict:
188 | raise ValueError(f"Payment {payment_id} does not have a value for {key}")
189 |
190 | return payment_dict[key]
191 |
192 | def set_payment_attribute(self, payment_id: int, key: str, value: Any):
193 | self.check_if_payment_exists(payment_id, raise_exception=True)
194 | self.payment_collection.update_one({"_id": payment_id}, {"$set": {key: value}})
195 |
196 | def get_all_not_expried_payment_ids(self):
197 | payments_find = self.payment_collection.find({
198 | "$and": [{"expired_at": {"$gt": datetime.now()}}, {"status": {"$ne": "paid"}}]
199 | })
200 | return [x["_id"] for x in payments_find]
201 |
202 | def create_newsletter(self, newsletter_id: str):
203 | if not self.check_if_newsletter_exists(newsletter_id):
204 | newsletter_dict = {
205 | "_id": newsletter_id,
206 | "already_sent_to_user_ids": [],
207 | "created_at": datetime.now()
208 | }
209 |
210 | self.newsletter_collection.insert_one(newsletter_dict)
211 |
212 | def add_user_to_newsletter(self, newsletter_id: str, user_id: int):
213 | self.check_if_newsletter_exists(newsletter_id, raise_exception=True)
214 | self.check_if_user_exists(user_id, raise_exception=True)
215 |
216 | newsletter_dict = self.newsletter_collection.find_one({"_id": newsletter_id})
217 | if user_id not in newsletter_dict["already_sent_to_user_ids"]:
218 | self.newsletter_collection.update_one(
219 | {"_id": newsletter_id},
220 | {"$push": {"already_sent_to_user_ids": user_id}}
221 | )
222 |
223 | def get_newsletter_attribute(self, newsletter_id: int, key: str):
224 | self.check_if_newsletter_exists(newsletter_id, raise_exception=True)
225 | newsletter_dict = self.newsletter_collection.find_one({"_id": newsletter_id})
226 |
227 | if key not in newsletter_dict:
228 | raise ValueError(f"Newsletter {newsletter_id} does not have a value for {key}")
229 |
230 | return newsletter_dict[key]
--------------------------------------------------------------------------------
/notebooks/analytics.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "65819b0d",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "%load_ext autoreload\n",
11 | "%autoreload 2\n",
12 | "\n",
13 | "import sys\n",
14 | "sys.path.append(\"..\")\n",
15 | "\n",
16 | "from collections import defaultdict\n",
17 | "from datetime import datetime\n",
18 | "import pymongo\n",
19 | "import pytz\n",
20 | "\n",
21 | "import pandas as pd\n",
22 | "from matplotlib import pylab as plt\n",
23 | "import seaborn as sns\n",
24 | "\n",
25 | "from bot import config\n",
26 | "from bot import database\n",
27 | "import numpy as np"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": null,
33 | "id": "ed48b96f",
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "db = database.Database()"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": null,
43 | "id": "9ddb85d6",
44 | "metadata": {},
45 | "outputs": [],
46 | "source": [
47 | "def change_tz_to_msk(d):\n",
48 | " return d.astimezone(pytz.timezone(\"Europe/Moscow\"))\n",
49 | "\n",
50 | "\n",
51 | "def user_to_str(user_dict):\n",
52 | " text = \"\"\n",
53 | " text += f\"{user_dict['_id']}:\\n\"\n",
54 | " for k in [\"username\", \"first_name\", \"last_name\", \"last_interaction\", \"first_seen\", \"current_chat_mode\", \"n_used_tokens\", \"token_balance\"]:\n",
55 | " if k in user_dict:\n",
56 | " v = user_dict[k]\n",
57 | " if isinstance(v, datetime):\n",
58 | " v = change_tz_to_msk(v)\n",
59 | " v = v.strftime('%H:%M:%S %d-%m-%Y')\n",
60 | " text += f\" - {k}: {v}\\n\"\n",
61 | "\n",
62 | " return text\n",
63 | "\n",
64 | "\n",
65 | "def dialog_to_str(dialog_dict):\n",
66 | " text = \"\"\n",
67 | " \n",
68 | " user_id = dialog_dict[\"user_id\"]\n",
69 | " user_dict = db.user_collection.find_one({\"_id\": user_id})\n",
70 | " \n",
71 | " text += user_to_str(user_dict)\n",
72 | " text += \"\\n\"\n",
73 | " \n",
74 | " text += f\"Chat mode: {dialog_dict['chat_mode']}\\n\\n\"\n",
75 | " text += \"Messages:\\n\"\n",
76 | " for message in dialog_dict[\"messages\"]:\n",
77 | " text += f\"U: {message['user']}\\n\"\n",
78 | " text += f\"B: {message['bot']}\\n\"\n",
79 | " text += \"\\n\"\n",
80 | " \n",
81 | " return text\n",
82 | "\n",
83 | "\n",
84 | "def payment_to_str(payment_dict):\n",
85 | " text = \"\"\n",
86 | " \n",
87 | " text += f\"Status: {payment_dict['status']}\\n\"\n",
88 | " date = change_tz_to_msk(payment_dict[\"created_at\"])\n",
89 | " text += f\"Date: {date}\\n\"\n",
90 | " text += f\"Amount: {payment_dict['amount']}\\n\\n\"\n",
91 | " \n",
92 | " user_id = payment_dict[\"user_id\"]\n",
93 | " user_dict = db.user_collection.find_one({\"_id\": user_id})\n",
94 | " \n",
95 | " text += user_to_str(user_dict)\n",
96 | " text += \"\\n\"\n",
97 | " \n",
98 | " return text"
99 | ]
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "id": "6c6998f8",
104 | "metadata": {},
105 | "source": [
106 | "### N total users"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "id": "6f54405e",
113 | "metadata": {},
114 | "outputs": [],
115 | "source": [
116 | "n_users = db.user_collection.count_documents({})\n",
117 | "print(f\"N total users: {n_users}\")"
118 | ]
119 | },
120 | {
121 | "cell_type": "markdown",
122 | "id": "ed7aab98",
123 | "metadata": {},
124 | "source": [
125 | "### Install graph"
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "execution_count": null,
131 | "id": "1e3b4741",
132 | "metadata": {},
133 | "outputs": [],
134 | "source": [
135 | "query = db.user_collection.find({})\n",
136 | "\n",
137 | "date_to_n_installs = defaultdict(int)\n",
138 | "for user_dict in list(query):\n",
139 | " date_to_n_installs[user_dict[\"first_seen\"].date()] += 1\n",
140 | "\n",
141 | "date_to_n_installs_tuples = list(date_to_n_installs.items())\n",
142 | "date_to_n_installs_tuples = sorted(date_to_n_installs_tuples, key=lambda x: x[0])\n",
143 | "\n",
144 | "df = pd.DataFrame(data={\n",
145 | " \"dates\": [x[0] for x in date_to_n_installs_tuples],\n",
146 | " \"installs\": [x[1] for x in date_to_n_installs_tuples]\n",
147 | "})\n",
148 | "\n",
149 | "fig, ax = plt.subplots(1, 1, figsize=(15, 5))\n",
150 | "sns.barplot(x='dates', y='installs', data=df, color=\"steelblue\")\n",
151 | "\n",
152 | "xticks = ax.get_xticks()\n",
153 | "xticklabels = [x.get_text() for x in ax.get_xticklabels()]\n",
154 | "_ = ax.set_xticks(xticks, xticklabels, rotation=90)"
155 | ]
156 | },
157 | {
158 | "cell_type": "markdown",
159 | "id": "42e090c1",
160 | "metadata": {},
161 | "source": [
162 | "### Install graph (cumsum)"
163 | ]
164 | },
165 | {
166 | "cell_type": "code",
167 | "execution_count": null,
168 | "id": "86f2dffc",
169 | "metadata": {},
170 | "outputs": [],
171 | "source": [
172 | "query = db.user_collection.find({})\n",
173 | "\n",
174 | "date_to_n_installs = defaultdict(int)\n",
175 | "for user_dict in list(query):\n",
176 | " date_to_n_installs[user_dict[\"first_seen\"].date()] += 1\n",
177 | "\n",
178 | "date_to_n_installs_tuples = list(date_to_n_installs.items())\n",
179 | "date_to_n_installs_tuples = sorted(date_to_n_installs_tuples, key=lambda x: x[0])\n",
180 | "\n",
181 | "df = pd.DataFrame(data={\n",
182 | " \"dates\": [x[0] for x in date_to_n_installs_tuples],\n",
183 | " \"installs\": np.cumsum([x[1] for x in date_to_n_installs_tuples])\n",
184 | "})\n",
185 | "\n",
186 | "fig, ax = plt.subplots(1, 1, figsize=(15, 5))\n",
187 | "sns.barplot(x='dates', y='installs', data=df, color=\"steelblue\")\n",
188 | "\n",
189 | "xticks = ax.get_xticks()\n",
190 | "xticklabels = [x.get_text() for x in ax.get_xticklabels()]\n",
191 | "_ = ax.set_xticks(xticks, xticklabels, rotation=90)"
192 | ]
193 | },
194 | {
195 | "cell_type": "markdown",
196 | "id": "962e3e33",
197 | "metadata": {},
198 | "source": [
199 | "### N total messages from users"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": null,
205 | "id": "c1b336cd",
206 | "metadata": {},
207 | "outputs": [],
208 | "source": [
209 | "query = db.dialog_collection.find({})\n",
210 | "\n",
211 | "n_total_messages_from_users = 0\n",
212 | "for dialog_dict in query:\n",
213 | " n_total_messages_from_users += len([1 for messages in dialog_dict[\"messages\"]])\n",
214 | " \n",
215 | "print(f\"N total messages from users: {n_total_messages_from_users}\")"
216 | ]
217 | },
218 | {
219 | "cell_type": "markdown",
220 | "id": "05dd0f97",
221 | "metadata": {},
222 | "source": [
223 | "### Message graph"
224 | ]
225 | },
226 | {
227 | "cell_type": "code",
228 | "execution_count": null,
229 | "id": "d89cd5de",
230 | "metadata": {},
231 | "outputs": [],
232 | "source": [
233 | "query = db.dialog_collection.find({})\n",
234 | "\n",
235 | "date_to_n_messages = defaultdict(int)\n",
236 | "for dialog_dict in query:\n",
237 | " for message in dialog_dict[\"messages\"]:\n",
238 | " date_to_n_messages[message[\"date\"].date()] += 1"
239 | ]
240 | },
241 | {
242 | "cell_type": "code",
243 | "execution_count": null,
244 | "id": "ab6513d5",
245 | "metadata": {},
246 | "outputs": [],
247 | "source": [
248 | "date_to_n_messages_tuples = list(date_to_n_messages.items())\n",
249 | "date_to_n_messages_tuples = sorted(date_to_n_messages_tuples, key=lambda x: x[0])\n",
250 | "\n",
251 | "df = pd.DataFrame(data={\n",
252 | " \"dates\": [x[0] for x in date_to_n_messages_tuples],\n",
253 | " \"messages\": [x[1] for x in date_to_n_messages_tuples],\n",
254 | "})\n",
255 | "\n",
256 | "fig, ax = plt.subplots(1, 1, figsize=(15, 5))\n",
257 | "sns.barplot(x='dates', y='messages', data=df, color=\"steelblue\")\n",
258 | "\n",
259 | "xticks = ax.get_xticks()\n",
260 | "xticklabels = [x.get_text() for x in ax.get_xticklabels()]\n",
261 | "_ = ax.set_xticks(xticks, xticklabels, rotation=90)"
262 | ]
263 | },
264 | {
265 | "cell_type": "markdown",
266 | "id": "fbd1967a",
267 | "metadata": {},
268 | "source": [
269 | "### Money graph"
270 | ]
271 | },
272 | {
273 | "cell_type": "code",
274 | "execution_count": null,
275 | "id": "4863b1d5",
276 | "metadata": {},
277 | "outputs": [],
278 | "source": [
279 | "query = db.payment_collection.find({\"status\": \"paid\"})\n",
280 | "\n",
281 | "date_to_money = defaultdict(int)\n",
282 | "for payment_dict in list(query):\n",
283 | " amount = payment_dict[\"amount\"]\n",
284 | " if payment_dict[\"currency\"] == \"RUB\":\n",
285 | " amount /= 77\n",
286 | " \n",
287 | " date_to_money[payment_dict[\"created_at\"].date()] += amount\n",
288 | "\n",
289 | "date_to_money_tuples = list(date_to_money.items())\n",
290 | "date_to_money_tuples = sorted(date_to_money_tuples, key=lambda x: x[0])\n",
291 | "\n",
292 | "df = pd.DataFrame(data={\n",
293 | " \"dates\": [x[0] for x in date_to_money_tuples],\n",
294 | " \"money\": [x[1] for x in date_to_money_tuples]\n",
295 | "})\n",
296 | "\n",
297 | "fig, ax = plt.subplots(1, 1, figsize=(15, 5))\n",
298 | "sns.barplot(x='dates', y='money', data=df, color=\"steelblue\")\n",
299 | "\n",
300 | "xticks = ax.get_xticks()\n",
301 | "xticklabels = [x.get_text() for x in ax.get_xticklabels()]\n",
302 | "_ = ax.set_xticks(xticks, xticklabels, rotation=90)\n",
303 | "\n",
304 | "print(f\"Total money: {sum(date_to_money.values())}\")"
305 | ]
306 | },
307 | {
308 | "cell_type": "markdown",
309 | "id": "2b217224",
310 | "metadata": {},
311 | "source": [
312 | "### Last registered users"
313 | ]
314 | },
315 | {
316 | "cell_type": "code",
317 | "execution_count": null,
318 | "id": "4559b6b8",
319 | "metadata": {},
320 | "outputs": [],
321 | "source": [
322 | "print(f\"5 last registered users:\\n\")\n",
323 | "\n",
324 | "query = db.user_collection.find().sort('first_seen', -1).limit(5)\n",
325 | "for user_dict in query:\n",
326 | " print(user_to_str(user_dict))\n",
327 | " print(\"_\" * 50, \"\\n\")"
328 | ]
329 | },
330 | {
331 | "cell_type": "markdown",
332 | "id": "bf66002a",
333 | "metadata": {},
334 | "source": [
335 | "### Last successful payments"
336 | ]
337 | },
338 | {
339 | "cell_type": "code",
340 | "execution_count": null,
341 | "id": "b895eb98",
342 | "metadata": {},
343 | "outputs": [],
344 | "source": [
345 | "print(f\"Last successful payments:\\n\")\n",
346 | "\n",
347 | "query = db.payment_collection.find({\"status\": \"paid\"}).sort(\"created_at\", -1).limit(5)\n",
348 | "for payment_dict in query:\n",
349 | " print(payment_to_str(payment_dict))\n",
350 | " print(\"_\" * 50, \"\\n\")"
351 | ]
352 | },
353 | {
354 | "cell_type": "markdown",
355 | "id": "de857a2d",
356 | "metadata": {},
357 | "source": [
358 | "### Last created payments"
359 | ]
360 | },
361 | {
362 | "cell_type": "code",
363 | "execution_count": null,
364 | "id": "21ec8237",
365 | "metadata": {},
366 | "outputs": [],
367 | "source": [
368 | "print(f\"Last created payments:\\n\")\n",
369 | "\n",
370 | "query = db.payment_collection.find({}).sort(\"created_at\", -1).limit(5)\n",
371 | "for payment_dict in query:\n",
372 | " print(payment_to_str(payment_dict))\n",
373 | " print(\"_\" * 50, \"\\n\")"
374 | ]
375 | },
376 | {
377 | "cell_type": "markdown",
378 | "id": "b519ca87",
379 | "metadata": {},
380 | "source": [
381 | "### Last dialogs"
382 | ]
383 | },
384 | {
385 | "cell_type": "code",
386 | "execution_count": null,
387 | "id": "18067535",
388 | "metadata": {
389 | "scrolled": false
390 | },
391 | "outputs": [],
392 | "source": [
393 | "query = db.dialog_collection.find({\"messages\": {\"$ne\": []}}).sort('start_time', -1).limit(30)\n",
394 | "for dialog_dict in query:\n",
395 | " print(dialog_to_str(dialog_dict))\n",
396 | " print(\"_\" * 50, \"\\n\")"
397 | ]
398 | }
399 | ],
400 | "metadata": {
401 | "kernelspec": {
402 | "display_name": "Python 3 (ipykernel)",
403 | "language": "python",
404 | "name": "python3"
405 | },
406 | "language_info": {
407 | "codemirror_mode": {
408 | "name": "ipython",
409 | "version": 3
410 | },
411 | "file_extension": ".py",
412 | "mimetype": "text/x-python",
413 | "name": "python",
414 | "nbconvert_exporter": "python",
415 | "pygments_lexer": "ipython3",
416 | "version": "3.8.16"
417 | }
418 | },
419 | "nbformat": 4,
420 | "nbformat_minor": 5
421 | }
422 |
--------------------------------------------------------------------------------
/bot/app.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 | import pymongo
4 | import asyncio
5 | import traceback
6 | import html
7 | import json
8 | import tempfile
9 | import pydub
10 | from pathlib import Path
11 | from datetime import datetime, timedelta
12 |
13 | import telegram
14 | from telegram import Update, User, InlineKeyboardButton, InlineKeyboardMarkup, LabeledPrice
15 | from telegram.ext import (
16 | ApplicationBuilder,
17 | CallbackContext,
18 | CommandHandler,
19 | MessageHandler,
20 | CallbackQueryHandler,
21 | PreCheckoutQueryHandler,
22 | JobQueue,
23 | AIORateLimiter,
24 | filters
25 | )
26 | from telegram.constants import ParseMode, ChatAction
27 |
28 | import cryptomus
29 |
30 | from bot import config
31 | from bot import database
32 | from bot import openai_utils
33 | from bot.payment import CryptomusPayment
34 |
35 |
36 | # setup
37 | db = database.Database()
38 | logger = logging.getLogger(__name__)
39 | user_semaphores = {}
40 |
41 | HELP_MESSAGE = """Commands:
42 | ⚪ /retry – Regenerate last bot answer
43 | ⚪ /new – Start new dialog
44 | ⚪ /mode – Select chat mode
45 | ⚪ /balance – Show balance
46 | ⚪ /help – Show help
47 |
48 | Important note 1. The longer your dialog, the more tokens are spent with each new message. To reset current dialog and start a new one, send /new command
49 |
50 | Important note 2. Write 🇬🇧 English for a better quality of answers
51 | """
52 |
53 |
54 | # --- Utility Functions --- #
55 | def split_text_into_chunks(text, chunk_size):
56 | for i in range(0, len(text), chunk_size):
57 | yield text[i:i + chunk_size]
58 |
59 |
60 | async def register_user(update: Update, context: CallbackContext, user: User):
61 | if not db.check_if_user_exists(user.id):
62 | db.add_new_user(
63 | user.id,
64 | update.message.chat_id,
65 | initial_token_balance=config.initial_token_balance,
66 | username=user.username,
67 | first_name=user.first_name,
68 | last_name= user.last_name
69 | )
70 | db.start_new_dialog(user.id)
71 |
72 | if db.get_user_attribute(user.id, "current_dialog_id") is None:
73 | db.start_new_dialog(user.id)
74 |
75 | # token balance
76 | if not db.check_if_user_attribute_exists(user.id, "token_balance"):
77 | db.set_user_attribute(user.id, "token_balance", config.initial_token_balance)
78 |
79 | # openai engine
80 | if not db.check_if_user_attribute_exists(user.id, "openai_engine"):
81 | openai_engine = "chatgpt" if config.use_chatgpt_api else "gpt"
82 | db.set_user_attribute(user.id, "openai_engine", openai_engine)
83 |
84 | if user.id not in user_semaphores:
85 | user_semaphores[user.id] = asyncio.Semaphore(1)
86 |
87 |
88 | async def is_previous_message_not_answered_yet(update: Update, context: CallbackContext):
89 | await register_user(update, context, update.message.from_user)
90 |
91 | user_id = update.message.from_user.id
92 | if user_semaphores[user_id].locked():
93 | text = "⏳ Please wait for a reply to the previous message"
94 | await update.message.reply_text(text, reply_to_message_id=update.message.id, parse_mode=ParseMode.HTML)
95 | return True
96 | else:
97 | return False
98 |
99 |
100 | async def check_if_user_has_enough_tokens(update: Update, context: CallbackContext):
101 | user_id = update.message.from_user.id
102 |
103 | token_balance = db.get_user_attribute(user_id, "token_balance")
104 | if token_balance <= 0:
105 | await show_balance_handle(update, context)
106 | return False
107 |
108 | return True
109 |
110 |
111 | async def send_user_message_about_n_added_tokens(context: CallbackContext, n_tokens_added: int, chat_id: int = None, user_id: int = None):
112 | if chat_id is None:
113 | if user_id is None:
114 | raise ValueError(f"chat_id and user_id can't be None simultaneously")
115 | chat_id = db.get_user_attribute(user_id, "chat_id")
116 |
117 | text = f"🟣 {n_tokens_added} tokens were successfully added to your balance!"
118 | await context.bot.send_message(chat_id, text, parse_mode=ParseMode.HTML)
119 |
120 |
121 | async def notify_admins_about_successfull_payment(context: CallbackContext, payment_id: int):
122 | if config.admin_chat_id is not None:
123 | text = "🟣 Successfull payment:\n"
124 |
125 | payment_dict = db.payment_collection.find_one({"_id": payment_id})
126 | for key in ["amount", "currency", "product_key", "n_tokens_to_add", "payment_method", "user_id", "status"]:
127 | text += f"- {key}: {payment_dict[key]}\n"
128 |
129 | user_dict = db.user_collection.find_one({"_id": payment_dict["user_id"]})
130 | if user_dict["username"] is not None:
131 | text += f"- username: @{user_dict['username']}\n"
132 |
133 | # tag admins
134 | for admin_username in config.admin_usernames:
135 | if not admin_username.startswith("@"):
136 | admin_username = "@" + admin_username
137 | text += f"\n{admin_username}"
138 |
139 | await context.bot.send_message(config.admin_chat_id, text, parse_mode=ParseMode.HTML)
140 |
141 |
142 | async def check_payment_status_job_fn(context: CallbackContext):
143 | job = context.job
144 | payment_id = job.data["payment_id"]
145 | payment_dict = db.payment_collection.find_one({"_id": payment_id})
146 |
147 | is_paid = False
148 | if payment_dict["payment_method_type"] == "cryptomus":
149 | cryptomus_payment_instance = CryptomusPayment(
150 | config.payment_methods["cryptomus"]["api_key"],
151 | config.payment_methods["cryptomus"]["merchant_id"]
152 | )
153 |
154 | is_paid = cryptomus_payment_instance.check_invoice_status(payment_id)
155 | else:
156 | context.job.schedule_removal()
157 | return
158 |
159 | if is_paid:
160 | db.set_payment_attribute(payment_id, "status", "paid")
161 | user_id = payment_dict["user_id"]
162 |
163 | n_tokens_to_add = payment_dict["n_tokens_to_add"]
164 | if not payment_dict["are_tokens_added"]:
165 | db.set_user_attribute(
166 | user_id,
167 | "token_balance",
168 | db.get_user_attribute(user_id, "token_balance") + n_tokens_to_add
169 | )
170 | db.set_payment_attribute(payment_id, "are_tokens_added", True)
171 |
172 | await send_user_message_about_n_added_tokens(context, n_tokens_to_add, chat_id=job.chat_id)
173 | await notify_admins_about_successfull_payment(context, payment_id)
174 |
175 | context.job.schedule_removal()
176 |
177 |
178 | def run_repeating_payment_status_check(job_queue: JobQueue, payment_id: int, chat_id: int, how_long: int = 4000, interval: int = 30):
179 | job_queue.run_repeating(
180 | check_payment_status_job_fn,
181 | interval,
182 | first=0,
183 | last=how_long,
184 | name=str(payment_id),
185 | data={"payment_id": payment_id},
186 | chat_id=chat_id
187 | )
188 |
189 |
190 | def run_not_expired_payment_status_check(job_queue: JobQueue, how_long: int = 4000, interval: int = 30):
191 | payment_ids = db.get_all_not_expried_payment_ids()
192 | for payment_id in payment_ids:
193 | user_id = db.get_payment_attribute(payment_id, "user_id")
194 | chat_id = db.get_user_attribute(user_id, "chat_id")
195 | run_repeating_payment_status_check(job_queue, payment_id, chat_id, how_long, interval)
196 |
197 |
198 |
199 | # --- System Handles --- #
200 | async def start_handle(update: Update, context: CallbackContext):
201 | await register_user(update, context, update.message.from_user)
202 | user_id = update.message.from_user.id
203 |
204 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
205 | db.start_new_dialog(user_id)
206 |
207 | reply_text = "Hi! I'm ChatGPT bot implemented with GPT-4 OpenAI API 🤖\n\n"
208 | reply_text += HELP_MESSAGE
209 |
210 | await update.message.reply_text(reply_text, parse_mode=ParseMode.HTML)
211 |
212 | async def show_chat_modes(context: CallbackContext):
213 | data = context.job.data
214 | await show_chat_modes_handle(data["update"], data["context"])
215 | context.job_queue.run_once(show_chat_modes, when=5, data={"update": update, "context": context})
216 |
217 |
218 | async def help_handle(update: Update, context: CallbackContext):
219 | await register_user(update, context, update.message.from_user)
220 | user_id = update.message.from_user.id
221 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
222 | await update.message.reply_text(HELP_MESSAGE, parse_mode=ParseMode.HTML)
223 |
224 |
225 |
226 | # --- Message Handles --- #
227 | async def message_handle(update: Update, context: CallbackContext, message=None, use_new_dialog_timeout=True):
228 | # check if message is edited
229 | if update.edited_message is not None:
230 | await edited_message_handle(update, context)
231 | return
232 |
233 | await register_user(update, context, update.message.from_user)
234 | if await is_previous_message_not_answered_yet(update, context): return
235 | if not await check_if_user_has_enough_tokens(update, context): return
236 |
237 | user_id = update.message.from_user.id
238 | chat_mode = db.get_user_attribute(user_id, "current_chat_mode")
239 |
240 | async with user_semaphores[user_id]:
241 | # new dialog timeout
242 | if use_new_dialog_timeout:
243 | if (datetime.now() - db.get_user_attribute(user_id, "last_interaction")).seconds > config.new_dialog_timeout and len(db.get_dialog_messages(user_id)) > 0:
244 | db.start_new_dialog(user_id)
245 | await update.message.reply_text(f"Starting new dialog due to timeout ({openai_utils.CHAT_MODES[chat_mode]['name']} mode) ✅", parse_mode=ParseMode.HTML)
246 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
247 |
248 | # send typing action
249 | await update.message.chat.send_action(action="typing")
250 |
251 | message = message or update.message.text
252 | dialog_messages = db.get_dialog_messages(user_id, dialog_id=None)
253 | use_chatgpt_api = db.get_user_attribute(user_id, "openai_engine") == "chatgpt"
254 | parse_mode = {
255 | "html": ParseMode.HTML,
256 | "markdown": ParseMode.MARKDOWN
257 | }[openai_utils.CHAT_MODES[chat_mode]["parse_mode"]]
258 |
259 | chatgpt_instance = openai_utils.ChatGPT(use_chatgpt_api=config.use_chatgpt_api)
260 | if config.enable_message_streaming:
261 | gen = chatgpt_instance.send_message_stream(message, dialog_messages=dialog_messages, chat_mode=chat_mode)
262 | else:
263 | answer, n_used_tokens, n_first_dialog_messages_removed = await chatgpt_instance.send_message(
264 | message,
265 | dialog_messages=dialog_messages,
266 | chat_mode=chat_mode
267 | )
268 |
269 | async def fake_gen():
270 | yield "finished", answer, n_used_tokens, n_first_dialog_messages_removed
271 |
272 | gen = fake_gen()
273 |
274 | # send message to user
275 | prev_answer = ""
276 | i = -1
277 | async for gen_item in gen:
278 | i += 1
279 |
280 | status = gen_item[0]
281 | if status == "not_finished":
282 | status, answer = gen_item
283 | elif status == "finished":
284 | status, answer, n_used_tokens, n_first_dialog_messages_removed = gen_item
285 | else:
286 | raise ValueError(f"Streaming status {status} is unknown")
287 |
288 | answer = answer[:4096] # telegram message limit
289 | if i == 0: # send first message (then it'll be edited if message streaming is enabled)
290 | try:
291 | sent_message = await update.message.reply_text(answer, parse_mode=parse_mode)
292 | except telegram.error.BadRequest as e:
293 | if str(e).startswith("Message must be non-empty"): # first answer chunk from openai was empty
294 | i = -1 # try again to send first message
295 | continue
296 | else:
297 | sent_message = await update.message.reply_text(answer)
298 | else: # edit sent message
299 | # update only when 100 new symbols are ready
300 | if abs(len(answer) - len(prev_answer)) < 100 and status != "finished":
301 | continue
302 |
303 | try:
304 | await context.bot.edit_message_text(answer, chat_id=sent_message.chat_id, message_id=sent_message.message_id, parse_mode=parse_mode)
305 | except telegram.error.BadRequest as e:
306 | if str(e).startswith("Message is not modified"):
307 | continue
308 | else:
309 | await context.bot.edit_message_text(answer, chat_id=sent_message.chat_id, message_id=sent_message.message_id)
310 |
311 | await asyncio.sleep(0.01) # wait a bit to avoid flooding
312 |
313 | prev_answer = answer
314 |
315 | # update user data
316 | new_dialog_message = {"user": message, "bot": answer, "date": datetime.now()}
317 | db.set_dialog_messages(
318 | user_id,
319 | db.get_dialog_messages(user_id, dialog_id=None) + [new_dialog_message],
320 | dialog_id=None
321 | )
322 |
323 | db.set_user_attribute(user_id, "n_used_tokens", n_used_tokens + db.get_user_attribute(user_id, "n_used_tokens"))
324 | db.set_user_attribute(user_id, "token_balance", max(0, db.get_user_attribute(user_id, "token_balance") - n_used_tokens))
325 |
326 | # send message if some messages were removed from the context
327 | if n_first_dialog_messages_removed > 0:
328 | if n_first_dialog_messages_removed == 1:
329 | text = "✍️ Note: Your current dialog is too long, so your first message was removed from the context.\n Send /new command to start new dialog"
330 | else:
331 | text = f"✍️ Note: Your current dialog is too long, so {n_first_dialog_messages_removed} first messages were removed from the context.\n Send /new command to start new dialog"
332 | await update.message.reply_text(text, parse_mode=ParseMode.HTML)
333 |
334 |
335 | async def edited_message_handle(update: Update, context: CallbackContext):
336 | text = "🥲 Unfortunately, message editing is not supported"
337 | await update.edited_message.reply_text(text, parse_mode=ParseMode.HTML)
338 |
339 |
340 | async def retry_handle(update: Update, context: CallbackContext):
341 | await register_user(update, context, update.message.from_user)
342 | if await is_previous_message_not_answered_yet(update, context): return
343 |
344 | user_id = update.message.from_user.id
345 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
346 |
347 | dialog_messages = db.get_dialog_messages(user_id, dialog_id=None)
348 | if len(dialog_messages) == 0:
349 | await update.message.reply_text("No message to retry 🤷♂️")
350 | return
351 |
352 | last_dialog_message = dialog_messages.pop()
353 | db.set_dialog_messages(user_id, dialog_messages, dialog_id=None) # last message was removed from the context
354 |
355 | await message_handle(update, context, message=last_dialog_message["user"], use_new_dialog_timeout=False)
356 |
357 |
358 | async def new_dialog_handle(update: Update, context: CallbackContext):
359 | await register_user(update, context, update.message.from_user)
360 | if await is_previous_message_not_answered_yet(update, context): return
361 |
362 | user_id = update.message.from_user.id
363 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
364 |
365 | db.start_new_dialog(user_id)
366 | await update.message.reply_text("Starting new dialog ✅")
367 |
368 | chat_mode = db.get_user_attribute(user_id, "current_chat_mode")
369 | await update.message.reply_text(f"{openai_utils.CHAT_MODES[chat_mode]['welcome_message']}", parse_mode=ParseMode.HTML)
370 |
371 |
372 | async def voice_message_handle(update: Update, context: CallbackContext):
373 | await register_user(update, context, update.message.from_user)
374 | if await is_previous_message_not_answered_yet(update, context): return
375 |
376 | user_id = update.message.from_user.id
377 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
378 |
379 | # check if user has enough tokens
380 | if not await check_if_user_has_enough_tokens(update, context):
381 | return
382 |
383 | voice = update.message.voice
384 | with tempfile.TemporaryDirectory() as tmp_dir:
385 | tmp_dir = Path(tmp_dir)
386 | voice_ogg_path = tmp_dir / "voice.ogg"
387 |
388 | # download
389 | voice_file = await context.bot.get_file(voice.file_id)
390 | await voice_file.download_to_drive(voice_ogg_path)
391 |
392 | # convert to mp3
393 | voice_mp3_path = tmp_dir / "voice.mp3"
394 | pydub.AudioSegment.from_file(voice_ogg_path).export(voice_mp3_path, format="mp3")
395 |
396 | # transcribe
397 | with open(voice_mp3_path, "rb") as f:
398 | transcribed_text = await openai_utils.transcribe_audio(f)
399 |
400 | text = f"🎤: {transcribed_text}"
401 | await update.message.reply_text(text, parse_mode=ParseMode.HTML)
402 |
403 | await message_handle(update, context, message=transcribed_text)
404 |
405 | # calculate spent dollars
406 | n_spent_dollars = voice.duration * (config.whisper_price_per_1_min / 60)
407 |
408 | # normalize dollars to tokens (it's very convenient to measure everything in a single unit)
409 | price_per_1000_tokens = config.chatgpt_price_per_1000_tokens if config.use_chatgpt_api else config.gpt_price_per_1000_tokens
410 | n_used_tokens = int(n_spent_dollars / (price_per_1000_tokens / 1000))
411 |
412 | db.set_user_attribute(user_id, "n_used_tokens", n_used_tokens + db.get_user_attribute(user_id, "n_used_tokens"))
413 | db.set_user_attribute(user_id, "token_balance", max(0, db.get_user_attribute(user_id, "token_balance") - n_used_tokens))
414 |
415 |
416 |
417 | # --- Chat Mode Handles --- #
418 | async def show_chat_modes_handle(update: Update, context: CallbackContext):
419 | await register_user(update, context, update.message.from_user)
420 | if await is_previous_message_not_answered_yet(update, context): return
421 |
422 | user_id = update.message.from_user.id
423 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
424 |
425 | keyboard = []
426 | for chat_mode, chat_mode_dict in openai_utils.CHAT_MODES.items():
427 | keyboard.append([InlineKeyboardButton(chat_mode_dict["name"], callback_data=f"set_chat_mode|{chat_mode}")])
428 | reply_markup = InlineKeyboardMarkup(keyboard)
429 |
430 | await update.message.reply_text("Select chat mode:", reply_markup=reply_markup)
431 |
432 |
433 | async def set_chat_mode_handle(update: Update, context: CallbackContext):
434 | await register_user(update.callback_query, context, update.callback_query.from_user)
435 | user_id = update.callback_query.from_user.id
436 |
437 | query = update.callback_query
438 | await query.answer()
439 |
440 | chat_mode = query.data.split("|")[1]
441 |
442 | db.set_user_attribute(user_id, "current_chat_mode", chat_mode)
443 | db.start_new_dialog(user_id)
444 |
445 | try:
446 | await query.edit_message_text(f"{openai_utils.CHAT_MODES[chat_mode]['welcome_message']}", parse_mode=ParseMode.HTML)
447 | except telegram.error.BadRequest as e:
448 | if str(e).startswith("Message is not modified"):
449 | pass
450 |
451 |
452 |
453 |
454 | # --- Payment Handles --- #
455 | async def show_balance_handle(update: Update, context: CallbackContext):
456 | await register_user(update, context, update.message.from_user)
457 | user_id = update.message.from_user.id
458 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
459 |
460 | token_balance = max(0, db.get_user_attribute(user_id, "token_balance"))
461 | n_used_tokens = db.get_user_attribute(user_id, "n_used_tokens")
462 |
463 | if token_balance > 0:
464 | text = f"🟢 You have {token_balance} tokens left\n"
465 | else:
466 | text = f"🔴 You have NO tokens left\n"
467 | text += f"You totally spent {n_used_tokens} tokens\n"
468 |
469 | reply_markup = InlineKeyboardMarkup([
470 | [InlineKeyboardButton("🥑 Get Tokens", callback_data=f"show_payment_methods")],
471 | ])
472 |
473 | await update.message.reply_text(text, reply_markup=reply_markup, parse_mode=ParseMode.HTML)
474 |
475 |
476 | async def show_payment_methods_handle(update: Update, context: CallbackContext):
477 | await register_user(update.callback_query, context, update.callback_query.from_user)
478 | user_id = update.callback_query.from_user.id
479 |
480 | query = update.callback_query
481 | await query.answer()
482 |
483 | text = "Choose payment method:"
484 |
485 | buttons = []
486 | for payment_method_key, payment_method_values in config.payment_methods.items():
487 | button = InlineKeyboardButton(
488 | payment_method_values["name"],
489 | callback_data=f"show_products|{payment_method_key}"
490 | )
491 | buttons.append([button])
492 | reply_markup = InlineKeyboardMarkup(buttons)
493 |
494 | await context.bot.send_message(
495 | update.callback_query.message.chat.id,
496 | text,
497 | reply_markup=reply_markup,
498 | parse_mode=ParseMode.HTML
499 | )
500 |
501 |
502 | async def show_products_handle(update: Update, context: CallbackContext):
503 | await register_user(update.callback_query, context, update.callback_query.from_user)
504 | user_id = update.callback_query.from_user.id
505 |
506 | query = update.callback_query
507 | await query.answer()
508 |
509 | _, payment_method_key = query.data.split("|")
510 |
511 | text = "How many tokens do you want to buy?"
512 |
513 | product_keys = config.payment_methods[payment_method_key]["product_keys"]
514 | buttons = []
515 | for product_key in product_keys:
516 | product = config.products[product_key]
517 | button = InlineKeyboardButton(
518 | product["title_on_button"],
519 | callback_data=f"send_invoice|{payment_method_key}|{product_key}"
520 | )
521 | buttons.append([button])
522 | reply_markup = InlineKeyboardMarkup(buttons)
523 |
524 | await context.bot.send_message(
525 | update.callback_query.message.chat.id,
526 | text,
527 | reply_markup=reply_markup,
528 | parse_mode=ParseMode.HTML
529 | )
530 |
531 |
532 | async def send_invoice_handle(update: Update, context: CallbackContext):
533 | await register_user(update.callback_query, context, update.callback_query.from_user)
534 | user_id = update.callback_query.from_user.id
535 |
536 | query = update.callback_query
537 | await query.answer()
538 |
539 | _, payment_method_key, product_key = query.data.split("|")
540 | product = config.products[product_key]
541 | payment_method_type = config.payment_methods[payment_method_key]["type"]
542 |
543 | payment_id = db.get_new_unique_payment_id()
544 |
545 | if payment_method_type == "telegram_payments":
546 | chat_id = update.callback_query.message.chat.id
547 |
548 | # save in database
549 | db.add_new_payment(
550 | payment_id=payment_id,
551 | payment_method=payment_method_key,
552 | payment_method_type=payment_method_type,
553 | product_key=product_key,
554 | user_id=user_id,
555 | amount=product["price"],
556 | currency=product["currency"],
557 | status="not_paid",
558 | invoice_url="",
559 | expired_at=datetime.now() + timedelta(hours=1),
560 | n_tokens_to_add=product["n_tokens_to_add"]
561 | )
562 |
563 | # create invoice
564 | payload = f"{payment_id}"
565 | prices = [LabeledPrice(product["title"], int(product["price"] * 100))]
566 |
567 | photo_url = None
568 | if "photo_url" in product and len(product["photo_url"]) > 0:
569 | photo_url = product["photo_url"]
570 |
571 | # send invoice
572 | await context.bot.send_invoice(
573 | chat_id,
574 | product["title"],
575 | product["description"],
576 | payload,
577 | config.payment_methods[payment_method_key]["token"],
578 | product["currency"],
579 | prices,
580 | photo_url=photo_url
581 | )
582 | elif payment_method_type == "cryptomus":
583 | # create invoice
584 | cryptomus_payment_instance = CryptomusPayment(
585 | config.payment_methods[payment_method_key]["api_key"],
586 | config.payment_methods[payment_method_key]["merchant_id"]
587 | )
588 |
589 | invoice_url, status, expired_at = cryptomus_payment_instance.create_invoice(
590 | payment_id,
591 | product["price"],
592 | product["currency"]
593 | )
594 |
595 | # save in database
596 | db.add_new_payment(
597 | payment_id=payment_id,
598 | payment_method=payment_method_key,
599 | payment_method_type=payment_method_type,
600 | product_key=product_key,
601 | user_id=user_id,
602 | amount=product["price"],
603 | currency=product["currency"],
604 | status=status,
605 | invoice_url=invoice_url,
606 | expired_at=expired_at,
607 | n_tokens_to_add=product["n_tokens_to_add"]
608 | )
609 |
610 | # run status check polling
611 | run_repeating_payment_status_check(context.job_queue, payment_id, update.callback_query.message.chat.id, how_long=4000, interval=30)
612 |
613 | # send invoice
614 | text = f"🔗 Here is: your invoice ({product['n_tokens_to_add']} tokens)\n\n"
615 | text += "You have 1 hour to pay it before it expires. If you are facing any problems, write to ."
616 | await context.bot.send_message(update.callback_query.message.chat.id, text, parse_mode=ParseMode.HTML)
617 | else:
618 | raise ValueError(f"Unknown payment method: {payment_method_type}")
619 |
620 |
621 | async def pre_checkout_handle(update: Update, context: CallbackContext):
622 | await register_user(update.pre_checkout_query, context, update.pre_checkout_query.from_user)
623 | user_id = update.pre_checkout_query.from_user.id
624 |
625 | query = update.pre_checkout_query
626 | await query.answer(ok=True)
627 |
628 |
629 | async def successful_payment_handle(update: Update, context: CallbackContext):
630 | await register_user(update, context, update.message.from_user)
631 | user_id = update.message.from_user.id
632 | chat_id = db.get_user_attribute(user_id, "chat_id")
633 |
634 | payment_id = int(update.message.successful_payment.invoice_payload)
635 | payment_dict = db.payment_collection.find_one({"_id": payment_id})
636 |
637 | # update payment in database
638 | db.set_payment_attribute(payment_id, "status", "paid")
639 |
640 | n_tokens_to_add = payment_dict["n_tokens_to_add"]
641 | if not payment_dict["are_tokens_added"]:
642 | db.set_user_attribute(
643 | user_id,
644 | "token_balance",
645 | db.get_user_attribute(user_id, "token_balance") + n_tokens_to_add
646 | )
647 | db.set_payment_attribute(payment_id, "are_tokens_added", True)
648 |
649 | # send messages
650 | await send_user_message_about_n_added_tokens(context, n_tokens_to_add, chat_id=chat_id)
651 | await notify_admins_about_successfull_payment(context, payment_id)
652 |
653 |
654 | # --- Admin Handles --- #
655 | async def add_tokens_handle(update: Update, context: CallbackContext):
656 | await register_user(update, context, update.message.from_user)
657 |
658 | username_or_user_id, n_tokens_to_add = context.args
659 | n_tokens_to_add = int(n_tokens_to_add)
660 |
661 | try:
662 | user_id = int(username_or_user_id)
663 | user_dict = db.user_collection.find_one({"_id": user_id})
664 | except:
665 | username = username_or_user_id
666 | user_dict = db.user_collection.find_one({"username": username})
667 |
668 | if user_dict is None:
669 | text = f"Username or user_id {username_or_user_id} not found in DB"
670 | await update.message.reply_text(text, parse_mode=ParseMode.HTML)
671 | return
672 |
673 | # add tokens
674 | db.set_user_attribute(user_dict["_id"], "token_balance", db.get_user_attribute(user_dict["_id"], "token_balance") + n_tokens_to_add)
675 |
676 | # send message to user
677 | await send_user_message_about_n_added_tokens(context, n_tokens_to_add, chat_id=user_dict["chat_id"])
678 |
679 | # send message to admin
680 | text = f"🟣 {n_tokens_to_add} tokens were successfully added to {username_or_user_id} balance!"
681 | await update.message.reply_text(text, parse_mode=ParseMode.HTML)
682 |
683 |
684 | async def switch_openai_engine_handle(update: Update, context: CallbackContext):
685 | await register_user(update, context, update.message.from_user)
686 | user_id = update.message.from_user.id
687 | db.set_user_attribute(user_id, "last_interaction", datetime.now())
688 |
689 | current_openai_engine = db.get_user_attribute(user_id, "openai_engine")
690 | if current_openai_engine == "chatgpt":
691 | new_openai_engine = "gpt"
692 | elif current_openai_engine == "gpt":
693 | new_openai_engine = "chatgpt"
694 | else:
695 | raise ValueError(f"Unknown OpenAI engine: {current_openai_engine}")
696 |
697 | db.set_user_attribute(user_id, "openai_engine", new_openai_engine)
698 |
699 | text = f"Switched to {new_openai_engine} engine ✅"
700 | await update.message.reply_text(text, parse_mode=ParseMode.HTML)
701 |
702 |
703 | async def user_info_handle(update: Update, context: CallbackContext):
704 | await register_user(update, context, update.message.from_user)
705 | user = update.message.from_user
706 |
707 | text = "User info:\n"
708 | text += f"- user_id: {user.id}\n"
709 | text += f"- username: {user.username}\n"
710 | text += f"- chat_id: {update.message.chat_id}\n"
711 |
712 | await update.message.reply_text(text, parse_mode=ParseMode.HTML)
713 | if config.admin_chat_id is not None:
714 | await context.bot.send_message(config.admin_chat_id, text, parse_mode=ParseMode.HTML)
715 |
716 |
717 | async def error_handle(update: Update, context: CallbackContext) -> None:
718 | logger.error(msg="Exception while handling an update:", exc_info=context.error)
719 |
720 | try:
721 | await context.bot.send_message(update.effective_chat.id, "🥲 Something went wrong...\nPlease try again later or contact !", parse_mode=ParseMode.HTML)
722 |
723 | if config.admin_chat_id is not None:
724 | # collect error message
725 | tb_list = traceback.format_exception(None, context.error, context.error.__traceback__)
726 | tb_string = "".join(tb_list)
727 | update_str = update.to_dict() if isinstance(update, Update) else str(update)
728 | message = (
729 | f"An exception was raised while handling an update\n"
730 | f"update = {html.escape(json.dumps(update_str, indent=2, ensure_ascii=False))}"
731 | "\n\n"
732 | f"{html.escape(tb_string)}"
733 | )
734 |
735 | # split text into multiple messages due to 4096 character limit
736 | for message_chunk in split_text_into_chunks(message, 4096):
737 | try:
738 | await context.bot.send_message(config.admin_chat_id, message_chunk, parse_mode=ParseMode.HTML)
739 | except telegram.error.BadRequest:
740 | # answer has invalid characters, so we send it without parse_mode
741 | await context.bot.send_message(config.admin_chat_id, message_chunk)
742 | except:
743 | await context.bot.send_message(update.effective_chat.id, "🥲 Some error in error handler... Contact ")
744 |
745 |
746 | def run_bot() -> None:
747 | application = (
748 | ApplicationBuilder()
749 | .token(config.telegram_token)
750 | .concurrent_updates(True)
751 | .rate_limiter(AIORateLimiter(max_retries=3))
752 | .http_version("1.1")
753 | .get_updates_http_version("1.1")
754 | .build()
755 | )
756 |
757 | # check not expired payments
758 | run_not_expired_payment_status_check(application.job_queue)
759 |
760 | # add handlers
761 | if len(config.allowed_telegram_usernames) == 0:
762 | user_filter = filters.ALL
763 | else:
764 | user_filter = filters.User(username=config.allowed_telegram_usernames)
765 |
766 | if len(config.admin_usernames) == 0:
767 | raise ValueError("You must specify at least 1 admin username in config")
768 | admin_filter = filters.User(username=config.admin_usernames)
769 |
770 | # system
771 | application.add_handler(CommandHandler("start", start_handle, filters=user_filter))
772 | application.add_handler(CommandHandler("help", help_handle, filters=user_filter))
773 |
774 | # message
775 | application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND & user_filter, message_handle))
776 | application.add_handler(CommandHandler("retry", retry_handle, filters=user_filter))
777 | application.add_handler(CommandHandler("new", new_dialog_handle, filters=user_filter))
778 | application.add_handler(MessageHandler(filters.VOICE & user_filter, voice_message_handle))
779 |
780 | # chat mode
781 | application.add_handler(CommandHandler("mode", show_chat_modes_handle, filters=user_filter))
782 | application.add_handler(CallbackQueryHandler(set_chat_mode_handle, pattern="^set_chat_mode"))
783 |
784 | # payment
785 | application.add_handler(CommandHandler("balance", show_balance_handle, filters=user_filter))
786 | application.add_handler(CallbackQueryHandler(show_payment_methods_handle, pattern="^show_payment_methods$"))
787 | application.add_handler(CallbackQueryHandler(show_products_handle, pattern="^show_products"))
788 | application.add_handler(CallbackQueryHandler(send_invoice_handle, pattern="^send_invoice"))
789 |
790 | application.add_handler(PreCheckoutQueryHandler(pre_checkout_handle))
791 | application.add_handler(MessageHandler(filters.SUCCESSFUL_PAYMENT & user_filter, successful_payment_handle))
792 |
793 | # admin
794 | application.add_handler(CommandHandler("add_tokens", add_tokens_handle, filters=admin_filter))
795 | application.add_handler(CommandHandler("switch_openai_engine", switch_openai_engine_handle, filters=user_filter))
796 | application.add_handler(CommandHandler("info", user_info_handle, filters=user_filter))
797 | application.add_error_handler(error_handle)
798 |
799 | # start the bot
800 | application.run_polling()
801 |
--------------------------------------------------------------------------------
/notebooks/newsletter_we_are_live_again.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "id": "4fde5eae",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "%load_ext autoreload\n",
11 | "%autoreload 2\n",
12 | "\n",
13 | "import sys\n",
14 | "sys.path.append(\"..\")\n",
15 | "\n",
16 | "import time\n",
17 | "import pymongo\n",
18 | "import datetime\n",
19 | "import pytz\n",
20 | "\n",
21 | "from telegram import InlineKeyboardButton, InlineKeyboardMarkup\n",
22 | "from telegram.ext import ApplicationBuilder\n",
23 | "from telegram.constants import ParseMode\n",
24 | "\n",
25 | "from bot import config\n",
26 | "from bot import database\n",
27 | "from bot.app import show_balance_handle"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": 2,
33 | "id": "1e4406c7",
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "application = (\n",
38 | " ApplicationBuilder()\n",
39 | " .token(config.telegram_token)\n",
40 | " .build()\n",
41 | ")\n",
42 | "\n",
43 | "db = database.Database()"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": 3,
49 | "id": "09464d20",
50 | "metadata": {},
51 | "outputs": [
52 | {
53 | "name": "stdout",
54 | "output_type": "stream",
55 | "text": [
56 | "Already sent to users: {1925283840, 384137216, 629866496, 1302204419, 5152628746, 457881611, 1398102028, 44099595, 516751375, 5347454992, 6004753, 6047741970, 302929939, 1043486741, 1875122198, 5627299861, 1184688152, 1204713497, 6215057431, 860700699, 6177658908, 1112305693, 818696222, 744362015, 13002777, 776855585, 1685334053, 931246118, 804155431, 5745397800, 1674692650, 5784668204, 1717964847, 560042032, 1207484464, 5789966391, 5233057849, 5707505724, 15822909, 9508927, 24221763, 1325080644, 760907844, 1268977734, 1128409158, 1176834119, 305776710, 157816900, 676034635, 67727436, 5315620938, 1507911762, 507740243, 104853593, 5675509854, 5030813792, 791939168, 5476204642, 5237954659, 738252901, 1081329768, 305123432, 1007302763, 1124974705, 1589088369, 1194973299, 787331195, 1132673149, 1171554430, 5052289151, 5215592583, 5600751753, 79120522, 630237321, 1860565132, 5451978892, 6727825, 5225973907, 1501374615, 5089786008, 524929177, 5277792410, 586029209, 5199341724, 1330782360, 1418571932, 1370306721, 6182533281, 720296100, 5475729573, 732512421, 5237350570, 1232339116, 289593517, 5251131566, 773488815, 5635727535, 932452530, 5401266357, 5598275766, 414318778, 2077425851, 5623771323, 1325932732, 836350139, 2128810177, 1077815490, 1795150018, 1128089796, 1483823297, 1771739346, 5000022227, 388894933, 5840857302, 1510985947, 873896155, 1019162846, 5013420256, 5254267105, 1553205474, 6109163749, 5171433704, 1344172268, 944128239, 1119389936, 273524979, 373674229, 5764417782, 1307986166, 838316281, 690579707, 1197644031, 976552192, 1125183744, 536815874, 101040390, 5056096519, 1014313227, 5603637516, 677081358, 1985816851, 972359959, 5310157080, 383312153, 5530882331, 5963491612, 852666653, 6149257501, 44095775, 1078608160, 1099073823, 948625701, 1607932199, 1175855403, 5045616941, 675893550, 900292911, 6016825650, 11630898, 394400053, 5347365175, 5595511096, 1269367097, 6075134266, 1258088764, 1112348989, 636207422, 144234822, 2133707081, 1905291594, 1531023691, 5032081740, 36114765, 1210618188, 1343488343, 218308952, 5165369692, 1214605664, 5784688992, 6004449635, 136145252, 828555620, 1544677735, 963637612, 1101498733, 5386740078, 5491390831, 564384112, 478108016, 479746418, 755540339, 211411316, 1732778357, 35551605, 5683429757, 256342401, 1488474498, 862982532, 717549957, 1925910927, 628117904, 1291815312, 2032540047, 1025044884, 210704789, 5726919061, 1704389016, 2042268056, 877633949, 1539078557, 387563935, 5577695650, 537586086, 1077338539, 1202825646, 629746102, 215310774, 944159161, 1578813890, 980754882, 1710197192, 340244939, 270780875, 1259839949, 801857996, 1064497615, 1348049359, 618521035, 1993908691, 1057360341, 1323614678, 1512292823, 958335447, 2005101018, 877359578, 861802974, 5230485983, 536941024, 5874325984, 525005282, 5852922339, 6406622, 42740197, 5336332774, 1176795624, 5164085739, 1312631275, 1660873197, 5708050925, 5561704941, 1082595819, 1724688885, 5289992694, 1639760376, 1255490045, 715741694, 2086119937, 793864706, 1092059651, 60703240, 5000020491, 984625675, 1548624395, 53975563, 61174284, 850270735, 5494723094, 975053335, 786084383, 692884004, 5114223141, 5534321190, 5611385382, 5052801576, 1774024623, 5022155308, 685898286, 1382949427, 5019591219, 5043524149, 5474097719, 5256356408, 1287610940, 5977977408, 1390719553, 5002936898, 676057669, 1217049157, 1148232261, 898376264, 1021745738, 1300200013, 1228376654, 1452366415, 160383568, 1036079699, 573102678, 552485462, 30310999, 1090939482, 1801341535, 492888672, 474933856, 7203424, 988910179, 16134757, 351195750, 1006889575, 5462632, 5870998119, 146539110, 1305373285, 1421701740, 1299839602, 5856354930, 350368373, 685841021, 891579006, 6288355967, 913007232, 1458420352, 2141870723, 1578377860, 5294539397, 916568707, 1223574165, 433969818, 1310935707, 6166364827, 5106348701, 489331358, 5672037025, 1068245666, 5219639970, 1146622626, 1576309413, 1876908710, 749486758, 383292068, 1489574571, 1282495147, 7191211, 2101971630, 554607279, 5602269872, 538372788, 139811512, 6273295038, 2061669054, 1963360964, 1307577029, 394404549, 1034017479, 6037340875, 5867602636, 1118925, 220865232, 332776145, 6208113372, 1542193885, 823624414, 491152096, 1196595937, 310368992, 1004911331, 1734740708, 484498149, 1472056038, 6213294823, 608959204, 906511082, 1926032108, 5483680493, 1332294382, 1964880626, 893211378, 211329780, 10005237, 2034776819, 719747831, 1495675641, 5370485499, 759775997, 396997375, 1351131904, 1694034689, 625588994, 6254711555, 635460356, 811707135, 1617353480, 1006277392, 810818321, 765969171, 1082682135, 433320730, 561322779, 5051138844, 1450201887, 1290955552, 7611179, 921924396, 516322093, 195228465, 6259538740, 292918071, 699654968, 5600277306, 5028707131, 1405408060, 1029905212, 1077826365, 629467976, 6763340, 5184461645, 5893153616, 325526352, 1165273939, 1240220503, 6282570587, 1758317408, 1163289440, 1476440930, 1353175907, 859470693, 1962969957, 975461225, 1134310250, 434355051, 5380453239, 505103225, 5158411130, 2111316859, 316861308, 1364900733, 144161659, 1873357697, 6270120835, 2121198468, 940688263, 1852296072, 1713830796, 268745615, 1907239824, 1150018448, 1250937749, 1019814806, 5824428956, 1038967711, 5039180704, 780233633, 1303466912, 251141027, 1381913508, 11176872, 5472244651, 796384173, 416465840, 1470815154, 1006390195, 1549632436, 908831671, 1125899192, 1491755960, 12506044, 1352733629, 5869687745, 920468427, 5595139019, 951905230, 5404027854, 195068884, 1738587098, 218983387, 1105189852, 988140508, 786901982, 152648671, 486321120, 6035211235, 1207503845, 611959785, 929919979, 839042028, 5620964337, 873171955, 172954615, 10757112, 1511693307, 5705501694, 5679074303, 1093886975, 1775621120, 137536512, 1315054594, 1913326597, 1290181639, 711826444, 5864582159, 5484891154, 424303636, 2125579284, 334277655, 154065947, 5524057122, 510792742, 1555475497, 1229429805, 6162492461, 775787571, 1085592629, 1790426165, 5109279801, 1271149631, 1047561281, 905339971, 1382607943, 1477463115, 792990798, 1287681102, 1237412942, 513254486, 5155931222, 100822102, 1941759065, 9733209, 6072097884, 1636318302, 5538972773, 5462252649, 697025642, 419292265, 702852201, 5514472559, 723305584, 433882230, 1420070007, 1098722423, 2008149116, 1150342269, 1780481149, 14918783, 1111391360, 871298177, 1662774402, 1672115331, 5963865219, 6024723587, 5476099207, 279450760, 439524497, 835996819, 1420344470, 262890648, 1225215131, 1302992028, 649114784, 1124502694, 1744960678, 1226493096, 5274303658, 2076888238, 5040929969, 5670423732, 1408152760, 6224860345, 909470906, 1122759876, 828351687, 485534926, 1269488847, 6689999, 2093747407, 223212754, 1437289686, 1066505431, 980696281, 1561148633, 547091675, 1203037404, 241349853, 663694558, 400346337, 1947512039, 6160813287, 142073065, 5340110057, 822635755, 1020210407, 800648429, 5438700779, 5155626223, 1177990383, 1513024753, 5556643059, 1774515444, 565304566, 574870778, 2131193082, 2103162113, 1026637061, 840199434, 1589607692, 1284261135, 1937423635, 753245463, 1383085335, 10089753, 5023098139, 900197661, 739781918, 725099806, 1787075872, 6004866337, 977009956, 165369124, 1684546858, 2135790892, 782402861, 820284717, 946476339, 1760040244, 5647656248, 980653368, 211027264, 272842049, 5683576132, 330511685, 404675912, 1562508618, 314367308, 5686605, 7501132, 1497304405, 416077141, 134151511, 1341582687, 5303887200, 5463225699, 1317277037, 981638509, 5351490927, 1142146416, 766823793, 1761052018, 1105261944, 218090873, 1141050748, 3288449, 833109378, 8957314, 1051966855, 2099842439, 17513864, 53026186, 645262734, 487542159, 971597200, 699798930, 1250575764, 834332055, 1028001176, 846251418, 540267931, 414262685, 5372284321, 6197298595, 182222243, 1420156323, 1579115940, 1997239715, 1251945897, 1729994155, 799479212, 5860300204, 792843693, 1966149040, 383460784, 1600660917, 5499622841, 1004490169, 617504186, 1339741631, 5227695553, 350729666, 961828291, 1124257222, 5491508680, 1662242250, 558974410, 9250257, 453141970, 5809595859, 211631570, 1008586197, 6117002711, 1293671896, 1370539481, 1772023255, 7443934, 489432545, 6895076, 1094061541, 1719385576, 1431139817, 921683433, 5010161131, 5630559725, 887256558, 643261940, 1851700728, 4251129, 903593465, 1261350396, 1392897532, 673777152, 1755942402, 400070146, 5084966406, 1445529095, 6204872199, 922146313, 5400899081, 5204624904, 6069888524, 6182792717, 5642370575, 1668228627, 177194518, 669949464, 1549293082, 831739418, 139992603, 1208555035, 1707660826, 1947973151, 94846496, 5201454623, 881628706, 742108707, 620195365, 791645734, 1893709355, 434216494, 76717614, 838569520, 1542686256, 1006829106, 2122745394, 470982196, 1034819124, 5466471994, 1699454523, 1048337982, 700812863, 5864580672, 5411630657, 16864838, 287374919, 361416262, 848655945, 707026508, 5873098317, 9121359, 1585364560, 127518290, 205663826, 1565496916, 994485845, 6702683, 1686842973, 5774319197, 646770270, 5418585697, 5461194338, 5011981924, 854060645, 169283175, 1749458537, 1678995050, 5580602989, 1447929454, 2116965997, 6138424948, 1128490617, 1513782906, 607116926, 5142296190, 5726094976, 5432131203, 35163779, 1865854598, 93349516, 1265565324, 721321614, 5454026383, 313091728, 14331534, 5368921749, 1856509591, 1479358111, 988382882, 141850278, 1512099497, 998962857, 5165047473, 1364401849, 5767669442, 528684739, 6082811588, 783961797, 758372036, 214204103, 1279270596, 1687269061, 5424836, 1653442253, 893132495, 747464405, 5775214293, 5213220568, 324069087, 1338336992, 611624673, 904900322, 937834211, 124796645, 1160814309, 784676583, 6038163176, 1201764073, 5178054377, 570423019, 287203051, 1546807022, 1650353904, 11329264, 1103693554, 1683824372, 907484916, 2022434551, 1797158647, 974581497, 107128570, 5224294137, 601806588, 18722558, 16420611, 5425866503, 923604744, 688826120, 1671053066, 714723086, 5338113807, 1122578192, 20832019, 210396948, 1971826455, 820041498, 227964699, 1189820193, 5616066338, 1256349477, 432144168, 6118383402, 1055686443, 5961338669, 5583904558, 5545398063, 5652819758, 6136944436, 912062262, 902209336, 373524290, 671498055, 5158313802, 1058873162, 673711951, 1080524631, 876715864, 1000046425, 454274906, 903290715, 1461485400, 5160185688, 11380569, 6080464735, 6230544224, 1367406431, 1933684572, 14319452, 623226727, 498798440, 1427320680, 1688686442, 600102759, 995540842, 100183920, 1579687792, 1253029750, 5876580219, 5342070652, 6098026366, 1633003393, 6043434884, 5353922437, 1401698182, 2023384969, 959162254, 804067221, 339320726, 5599688599, 2023104410, 1148043163, 74225564, 1455540126, 5621665696, 401860513, 172199844, 798496677, 5080977317, 6105884583, 80203691, 5073366957, 1080045486, 726351791, 1887649710, 1248946097, 946069426, 5326147507, 5981616052, 1081370544, 547659699, 475422642, 642999, 1948491705, 1233332156, 5864841153, 1290160066, 3786694, 615479238, 1639186376, 878671814, 1418610634, 5849720779, 585088972, 5208004559, 1988304847, 5650110417, 1016745939, 1314138068, 7167964, 1377384424, 65746922, 5936754668, 1910239214, 5469163503, 564692978, 6676467, 986384372, 1040648182, 1748502520, 782252025, 5358643195, 1526722557}\n"
57 | ]
58 | }
59 | ],
60 | "source": [
61 | "newsletter_id = \"we_are_live_again\"\n",
62 | "\n",
63 | "db.create_newsletter(newsletter_id)\n",
64 | "already_sent_to_user_ids = set(db.get_newsletter_attribute(newsletter_id, \"already_sent_to_user_ids\"))\n",
65 | "\n",
66 | "print(f\"Already sent to users: {already_sent_to_user_ids}\")"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "execution_count": 4,
72 | "id": "0c03345d",
73 | "metadata": {},
74 | "outputs": [
75 | {
76 | "name": "stdout",
77 | "output_type": "stream",
78 | "text": [
79 | "Found 7644 users\n"
80 | ]
81 | }
82 | ],
83 | "source": [
84 | "# user_dicts = list(db.user_collection.find({\"username\": \"karfly\"}))\n",
85 | "user_dicts = list(db.user_collection.find({\"first_seen\": {\"$gte\": datetime.datetime(2023, 3, 18)}}))\n",
86 | "print(f\"Found {len(user_dicts)} users\")"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": null,
92 | "id": "17a40c58",
93 | "metadata": {},
94 | "outputs": [
95 | {
96 | "name": "stdout",
97 | "output_type": "stream",
98 | "text": [
99 | "Skipping 1390719553. Already sent before\n",
100 | "Skipping 5454026383. Already sent before\n",
101 | "Skipping 10757112. Already sent before\n",
102 | "Skipping 922146313. Already sent before\n",
103 | "Skipping 1093886975. Already sent before\n",
104 | "Skipping 1472056038. Already sent before\n",
105 | "Skipping 977009956. Already sent before\n",
106 | "Skipping 5158313802. Already sent before\n",
107 | "Skipping 573102678. Already sent before\n",
108 | "Skipping 401860513. Already sent before\n",
109 | "Skipping 1549293082. Already sent before\n",
110 | "Skipping 396997375. Already sent before\n",
111 | "Skipping 1077338539. Already sent before\n",
112 | "Skipping 42740197. Already sent before\n",
113 | "Skipping 988382882. Already sent before\n",
114 | "Skipping 1450201887. Already sent before\n",
115 | "Skipping 1134310250. Already sent before\n",
116 | "Skipping 1455540126. Already sent before\n",
117 | "Skipping 1749458537. Already sent before\n",
118 | "Skipping 554607279. Already sent before\n",
119 | "Skipping 944159161. Already sent before\n",
120 | "Skipping 804155431. Already sent before\n",
121 | "Skipping 1111391360. Already sent before\n",
122 | "Skipping 1014313227. Already sent before\n",
123 | "Skipping 1578813890. Already sent before\n",
124 | "Skipping 134151511. Already sent before\n",
125 | "Skipping 1000046425. Already sent before\n",
126 | "Skipping 1223574165. Already sent before\n",
127 | "Skipping 838569520. Already sent before\n",
128 | "Skipping 931246118. Already sent before\n",
129 | "Skipping 1585364560. Already sent before\n",
130 | "Skipping 1639760376. Already sent before\n",
131 | "Skipping 1150342269. Already sent before\n",
132 | "Skipping 800648429. Already sent before\n",
133 | "Skipping 908831671. Already sent before\n",
134 | "Skipping 913007232. Already sent before\n",
135 | "Skipping 100183920. Already sent before\n",
136 | "Skipping 302929939. Already sent before\n",
137 | "Skipping 1893709355. Already sent before\n",
138 | "Skipping 433320730. Already sent before\n",
139 | "Skipping 1801341535. Already sent before\n",
140 | "Skipping 107128570. Already sent before\n",
141 | "Skipping 1704389016. Already sent before\n",
142 | "Skipping 1418610634. Already sent before\n",
143 | "Failed to send message to 980937318. Reason: Forbidden: bot was blocked by the user\n",
144 | "Skipping 11176872. Already sent before\n",
145 | "Skipping 5534321190. Already sent before\n",
146 | "Skipping 5073366957. Already sent before\n",
147 | "Skipping 5418585697. Already sent before\n",
148 | "Skipping 2005101018. Already sent before\n",
149 | "Skipping 433969818. Already sent before\n",
150 | "Failed to send message to 726275073. Reason: Forbidden: bot was blocked by the user\n",
151 | "Skipping 1271149631. Already sent before\n",
152 | "Skipping 738252901. Already sent before\n",
153 | "Skipping 831739418. Already sent before\n",
154 | "Skipping 2103162113. Already sent before\n",
155 | "Failed to send message to 1536898027. Reason: Forbidden: bot was blocked by the user\n",
156 | "Skipping 891579006. Already sent before\n",
157 | "Skipping 1926032108. Already sent before\n",
158 | "Skipping 1748502520. Already sent before\n",
159 | "Failed to send message to 1970775756. Reason: Forbidden: bot was blocked by the user\n",
160 | "Skipping 3786694. Already sent before\n",
161 | "Skipping 313091728. Already sent before\n",
162 | "Skipping 1332294382. Already sent before\n",
163 | "Skipping 753245463. Already sent before\n",
164 | "Skipping 5621665696. Already sent before\n",
165 | "Skipping 643261940. Already sent before\n",
166 | "Skipping 18722558. Already sent before\n",
167 | "Skipping 951905230. Already sent before\n",
168 | "Skipping 1229429805. Already sent before\n",
169 | "Skipping 1189820193. Already sent before\n",
170 | "Skipping 241349853. Already sent before\n",
171 | "Skipping 776855585. Already sent before\n",
172 | "Skipping 1048337982. Already sent before\n",
173 | "Skipping 5351490927. Already sent before\n",
174 | "Skipping 1268977734. Already sent before\n",
175 | "Skipping 786084383. Already sent before\n",
176 | "Skipping 5864582159. Already sent before\n",
177 | "Skipping 127518290. Already sent before\n",
178 | "Skipping 1085592629. Already sent before\n",
179 | "Skipping 144234822. Already sent before\n",
180 | "Skipping 2022434551. Already sent before\n",
181 | "Skipping 6004866337. Already sent before\n",
182 | "Skipping 1080045486. Already sent before\n",
183 | "Skipping 332776145. Already sent before\n",
184 | "Skipping 404675912. Already sent before\n",
185 | "Skipping 1790426165. Already sent before\n",
186 | "Skipping 1310935707. Already sent before\n",
187 | "Skipping 5462632. Already sent before\n",
188 | "Skipping 1699454523. Already sent before\n",
189 | "Skipping 1686842973. Already sent before\n",
190 | "Skipping 1119389936. Already sent before\n",
191 | "Skipping 1865854598. Already sent before\n",
192 | "Skipping 921924396. Already sent before\n",
193 | "Skipping 1122759876. Already sent before\n",
194 | "Failed to send message to 2092138910. Reason: Forbidden: bot was blocked by the user\n",
195 | "Skipping 799479212. Already sent before\n",
196 | "Skipping 6038163176. Already sent before\n",
197 | "Skipping 1092059651. Already sent before\n",
198 | "Skipping 6230544224. Already sent before\n",
199 | "Skipping 5705501694. Already sent before\n",
200 | "Skipping 1780481149. Already sent before\n",
201 | "Skipping 1051966855. Already sent before\n",
202 | "Skipping 574870778. Already sent before\n",
203 | "Skipping 5386740078. Already sent before\n",
204 | "Skipping 791645734. Already sent before\n",
205 | "Skipping 2086119937. Already sent before\n",
206 | "Skipping 218090873. Already sent before\n",
207 | "Skipping 873171955. Already sent before\n",
208 | "Skipping 5336332774. Already sent before\n",
209 | "Skipping 491152096. Already sent before\n",
210 | "Skipping 5466471994. Already sent before\n",
211 | "Failed to send message to 1407643629. Reason: Forbidden: bot was blocked by the user\n",
212 | "Skipping 607116926. Already sent before\n",
213 | "Skipping 871298177. Already sent before\n",
214 | "Skipping 1344172268. Already sent before\n",
215 | "Skipping 564384112. Already sent before\n",
216 | "Skipping 6117002711. Already sent before\n",
217 | "Skipping 1636318302. Already sent before\n",
218 | "Skipping 1510985947. Already sent before\n",
219 | "Skipping 5670423732. Already sent before\n",
220 | "Skipping 6016825650. Already sent before\n",
221 | "Skipping 1512099497. Already sent before\n",
222 | "Skipping 6270120835. Already sent before\n",
223 | "Skipping 862982532. Already sent before\n",
224 | "Skipping 903290715. Already sent before\n",
225 | "Skipping 1232339116. Already sent before\n",
226 | "Failed to send message to 5992071686. Reason: Forbidden: bot was blocked by the user\n",
227 | "Skipping 24221763. Already sent before\n",
228 | "Skipping 210704789. Already sent before\n",
229 | "Skipping 6037340875. Already sent before\n",
230 | "Skipping 726351791. Already sent before\n",
231 | "Skipping 747464405. Already sent before\n",
232 | "Failed to send message to 1067402085. Reason: Forbidden: bot was blocked by the user\n",
233 | "Skipping 1255490045. Already sent before\n",
234 | "Skipping 818696222. Already sent before\n",
235 | "Skipping 2133707081. Already sent before\n",
236 | "Skipping 798496677. Already sent before\n",
237 | "Skipping 1077815490. Already sent before\n",
238 | "Failed to send message to 1081697845. Reason: Forbidden: bot was blocked by the user\n",
239 | "Skipping 1774515444. Already sent before\n",
240 | "Skipping 5370485499. Already sent before\n",
241 | "Failed to send message to 1600969598. Reason: Forbidden: bot was blocked by the user\n",
242 | "Skipping 988910179. Already sent before\n",
243 | "Skipping 1203037404. Already sent before\n",
244 | "Skipping 5600277306. Already sent before\n",
245 | "Skipping 489331358. Already sent before\n",
246 | "Skipping 1124502694. Already sent before\n",
247 | "Skipping 6105884583. Already sent before\n",
248 | "Skipping 860700699. Already sent before\n",
249 | "Skipping 5401266357. Already sent before\n",
250 | "Skipping 538372788. Already sent before\n",
251 | "Skipping 5045616941. Already sent before\n",
252 | "Skipping 5164085739. Already sent before\n",
253 | "Skipping 5647656248. Already sent before\n",
254 | "Skipping 528684739. Already sent before\n",
255 | "Skipping 6072097884. Already sent before\n",
256 | "Skipping 1141050748. Already sent before\n",
257 | "Skipping 1948491705. Already sent before\n",
258 | "Skipping 1160814309. Already sent before\n",
259 | "Skipping 67727436. Already sent before\n",
260 | "Failed to send message to 94985126. Reason: Forbidden: bot was blocked by the user\n",
261 | "Skipping 1420070007. Already sent before\n",
262 | "Skipping 211329780. Already sent before\n",
263 | "Skipping 881628706. Already sent before\n",
264 | "Skipping 5233057849. Already sent before\n",
265 | "Skipping 5726919061. Already sent before\n",
266 | "Skipping 1660873197. Already sent before\n",
267 | "Skipping 536941024. Already sent before\n",
268 | "Skipping 5679074303. Already sent before\n",
269 | "Skipping 5056096519. Already sent before\n",
270 | "Skipping 1057360341. Already sent before\n",
271 | "Failed to send message to 821670964. Reason: Forbidden: bot was blocked by the user\n",
272 | "Skipping 1124974705. Already sent before\n",
273 | "Skipping 5708050925. Already sent before\n",
274 | "Skipping 287374919. Already sent before\n",
275 | "Skipping 873896155. Already sent before\n",
276 | "Skipping 1738587098. Already sent before\n",
277 | "Skipping 5080977317. Already sent before\n",
278 | "Skipping 485534926. Already sent before\n",
279 | "Skipping 1214605664. Already sent before\n",
280 | "Failed to send message to 13269077. Reason: Forbidden: bot was blocked by the user\n",
281 | "Skipping 5461194338. Already sent before\n",
282 | "Skipping 1098722423. Already sent before\n",
283 | "Skipping 1941759065. Already sent before\n",
284 | "Skipping 6035211235. Already sent before\n",
285 | "Skipping 1078608160. Already sent before\n",
286 | "Skipping 424303636. Already sent before\n",
287 | "Skipping 1290160066. Already sent before\n",
288 | "Skipping 5874325984. Already sent before\n",
289 | "Skipping 498798440. Already sent before\n",
290 | "Skipping 5789966391. Already sent before\n",
291 | "Skipping 1546807022. Already sent before\n",
292 | "Skipping 1937423635. Already sent before\n",
293 | "Skipping 994485845. Already sent before\n",
294 | "Skipping 5368921749. Already sent before\n",
295 | "Skipping 976552192. Already sent before\n",
296 | "Skipping 1553205474. Already sent before\n",
297 | "Skipping 79120522. Already sent before\n",
298 | "Skipping 1672115331. Already sent before\n",
299 | "Skipping 1259839949. Already sent before\n",
300 | "Skipping 432144168. Already sent before\n",
301 | "Skipping 5686605. Already sent before\n",
302 | "Skipping 6213294823. Already sent before\n",
303 | "Skipping 1476440930. Already sent before\n",
304 | "Skipping 5852922339. Already sent before\n",
305 | "Skipping 1966149040. Already sent before\n",
306 | "Skipping 792990798. Already sent before\n",
307 | "Skipping 6197298595. Already sent before\n",
308 | "Skipping 2111316859. Already sent before\n",
309 | "Skipping 5600751753. Already sent before\n",
310 | "Skipping 394400053. Already sent before\n",
311 | "Skipping 524929177. Already sent before\n",
312 | "Skipping 1512292823. Already sent before\n",
313 | "Skipping 840199434. Already sent before\n",
314 | "Skipping 1352733629. Already sent before\n",
315 | "Failed to send message to 5407093621. Reason: Forbidden: bot was blocked by the user\n",
316 | "Skipping 5230485983. Already sent before\n",
317 | "Skipping 53026186. Already sent before\n",
318 | "Skipping 630237321. Already sent before\n",
319 | "Skipping 94846496. Already sent before\n",
320 | "Skipping 454274906. Already sent before\n",
321 | "Skipping 1250575764. Already sent before\n",
322 | "Skipping 1925283840. Already sent before\n",
323 | "Skipping 384137216. Already sent before\n",
324 | "Skipping 700812863. Already sent before\n",
325 | "Skipping 904900322. Already sent before\n",
326 | "Skipping 5165369692. Already sent before\n",
327 | "Skipping 1343488343. Already sent before\n",
328 | "Skipping 1253029750. Already sent before\n",
329 | "Skipping 900197661. Already sent before\n",
330 | "Skipping 1542193885. Already sent before\n",
331 | "Skipping 5084966406. Already sent before\n",
332 | "Skipping 6177658908. Already sent before\n",
333 | "Skipping 1662774402. Already sent before\n",
334 | "Skipping 350729666. Already sent before\n",
335 | "Skipping 2121198468. Already sent before\n",
336 | "Skipping 1875122198. Already sent before\n",
337 | "Skipping 5538972773. Already sent before\n",
338 | "Skipping 2023104410. Already sent before\n",
339 | "Skipping 717549957. Already sent before\n",
340 | "Skipping 822635755. Already sent before\n",
341 | "Skipping 1633003393. Already sent before\n",
342 | "Skipping 1947973151. Already sent before\n",
343 | "Skipping 1856509591. Already sent before\n",
344 | "Skipping 5199341724. Already sent before\n",
345 | "Skipping 629866496. Already sent before\n",
346 | "Skipping 434355051. Already sent before\n",
347 | "Skipping 1887649710. Already sent before\n",
348 | "Failed to send message to 1130794177. Reason: Forbidden: bot was blocked by the user\n",
349 | "Skipping 1105261944. Already sent before\n",
350 | "Skipping 5491508680. Already sent before\n",
351 | "Skipping 2077425851. Already sent before\n",
352 | "Skipping 5155626223. Already sent before\n",
353 | "Skipping 887256558. Already sent before\n",
354 | "Skipping 5873098317. Already sent before\n",
355 | "Skipping 5864841153. Already sent before\n",
356 | "Skipping 5484891154. Already sent before\n",
357 | "Skipping 5981616052. Already sent before\n",
358 | "Skipping 1302992028. Already sent before\n",
359 | "Skipping 36114765. Already sent before\n",
360 | "Skipping 152648671. Already sent before\n",
361 | "Skipping 766823793. Already sent before\n",
362 | "Skipping 7167964. Already sent before\n",
363 | "Skipping 142073065. Already sent before\n",
364 | "Skipping 11630898. Already sent before\n",
365 | "Skipping 1299839602. Already sent before\n",
366 | "Skipping 6075134266. Already sent before\n",
367 | "Skipping 1118925. Already sent before\n",
368 | "Skipping 5745397800. Already sent before\n",
369 | "Skipping 1925910927. Already sent before\n",
370 | "Skipping 5400899081. Already sent before\n",
371 | "Skipping 5876580219. Already sent before\n",
372 | "Skipping 1760040244. Already sent before\n",
373 | "Skipping 838316281. Already sent before\n",
374 | "Skipping 6288355967. Already sent before\n",
375 | "Skipping 1184688152. Already sent before\n",
376 | "Skipping 316861308. Already sent before\n",
377 | "Skipping 470982196. Already sent before\n",
378 | "Skipping 5580602989. Already sent before\n",
379 | "Skipping 2076888238. Already sent before\n",
380 | "Skipping 1964880626. Already sent before\n",
381 | "Skipping 1405408060. Already sent before\n",
382 | "Skipping 6080464735. Already sent before\n",
383 | "Skipping 1006829106. Already sent before\n",
384 | "Skipping 783961797. Already sent before\n",
385 | "Skipping 5623771323. Already sent before\n",
386 | "Skipping 2135790892. Already sent before\n",
387 | "Failed to send message to 1248978353. Reason: Forbidden: bot was blocked by the user\n",
388 | "Skipping 44095775. Already sent before\n",
389 | "Skipping 5530882331. Already sent before\n",
390 | "Skipping 60703240. Already sent before\n",
391 | "Skipping 649114784. Already sent before\n",
392 | "Skipping 1034017479. Already sent before\n",
393 | "Skipping 972359959. Already sent before\n",
394 | "Skipping 5326147507. Already sent before\n",
395 | "Skipping 5620964337. Already sent before\n",
396 | "Skipping 1302204419. Already sent before\n",
397 | "Skipping 537586086. Already sent before\n",
398 | "Failed to send message to 1402693515. Reason: Forbidden: bot was blocked by the user\n",
399 | "Skipping 787331195. Already sent before\n",
400 | "Skipping 74225564. Already sent before\n",
401 | "Skipping 1125899192. Already sent before\n",
402 | "Skipping 2128810177. Already sent before\n",
403 | "Skipping 1300200013. Already sent before\n",
404 | "Skipping 1579687792. Already sent before\n",
405 | "Skipping 350368373. Already sent before\n",
406 | "Skipping 2099842439. Already sent before\n",
407 | "Skipping 5277792410. Already sent before\n",
408 | "Skipping 742108707. Already sent before\n",
409 | "Skipping 6136944436. Already sent before\n",
410 | "Skipping 852666653. Already sent before\n",
411 | "Skipping 1420344470. Already sent before\n",
412 | "Skipping 1549632436. Already sent before\n",
413 | "Skipping 1006277392. Already sent before\n",
414 | "Skipping 10089753. Already sent before\n",
415 | "Skipping 1043486741. Already sent before\n",
416 | "Skipping 1797158647. Already sent before\n",
417 | "Skipping 673711951. Already sent before\n",
418 | "Skipping 5022155308. Already sent before\n",
419 | "Skipping 5514472559. Already sent before\n",
420 | "Skipping 1437289686. Already sent before\n",
421 | "Skipping 5000020491. Already sent before\n",
422 | "Failed to send message to 425760967. Reason: Forbidden: bot was blocked by the user\n",
423 | "Skipping 1445529095. Already sent before\n",
424 | "Skipping 1501374615. Already sent before\n",
425 | "Skipping 848655945. Already sent before\n",
426 | "Skipping 980696281. Already sent before\n",
427 | "Skipping 1312631275. Already sent before\n",
428 | "Skipping 1713830796. Already sent before\n",
429 | "Skipping 5561704941. Already sent before\n",
430 | "Skipping 1058873162. Already sent before\n",
431 | "Skipping 5867602636. Already sent before\n",
432 | "Skipping 561322779. Already sent before\n",
433 | "Skipping 1175855403. Already sent before\n",
434 | "Skipping 5603637516. Already sent before\n",
435 | "Skipping 1477463115. Already sent before\n",
436 | "Skipping 1006889575. Already sent before\n",
437 | "Skipping 5494723094. Already sent before\n",
438 | "Skipping 1351131904. Already sent before\n",
439 | "Skipping 1148043163. Already sent before\n",
440 | "Skipping 6082811588. Already sent before\n",
441 | "Failed to send message to 5213904503. Reason: Forbidden: bot was blocked by the user\n",
442 | "Skipping 1683824372. Already sent before\n",
443 | "Skipping 765969171. Already sent before\n",
444 | "Skipping 324069087. Already sent before\n",
445 | "Skipping 6098026366. Already sent before\n",
446 | "Skipping 1201764073. Already sent before\n",
447 | "Skipping 697025642. Already sent before\n",
448 | "Skipping 1287681102. Already sent before\n",
449 | "Skipping 586029209. Already sent before\n",
450 | "Skipping 1678995050. Already sent before\n",
451 | "Skipping 5774319197. Already sent before\n",
452 | "Skipping 1852296072. Already sent before\n",
453 | "Skipping 984625675. Already sent before\n",
454 | "Skipping 6149257501. Already sent before\n",
455 | "Failed to send message to 1291244268. Reason: Forbidden: bot was blocked by the user\n",
456 | "Skipping 5089786008. Already sent before\n",
457 | "Skipping 5784688992. Already sent before\n",
458 | "Skipping 1068245666. Already sent before\n",
459 | "Skipping 330511685. Already sent before\n",
460 | "Skipping 5583904558. Already sent before\n",
461 | "Skipping 492888672. Already sent before\n",
462 | "Skipping 1617353480. Already sent before\n",
463 | "Skipping 1330782360. Already sent before\n",
464 | "Skipping 195068884. Already sent before\n",
465 | "Skipping 5032081740. Already sent before\n",
466 | "Skipping 775787571. Already sent before\n",
467 | "Skipping 5462252649. Already sent before\n",
468 | "Skipping 210396948. Already sent before\n",
469 | "Skipping 5556643059. Already sent before\n",
470 | "Skipping 946069426. Already sent before\n",
471 | "Skipping 2125579284. Already sent before\n",
472 | "Skipping 1787075872. Already sent before\n",
473 | "Skipping 5152628746. Already sent before\n",
474 | "Skipping 629467976. Already sent before\n",
475 | "Skipping 5208004559. Already sent before\n",
476 | "Skipping 1860565132. Already sent before\n",
477 | "Skipping 540267931. Already sent before\n",
478 | "Skipping 5158411130. Already sent before\n",
479 | "Skipping 1851700728. Already sent before\n",
480 | "Skipping 93349516. Already sent before\n",
481 | "Skipping 182222243. Already sent before\n",
482 | "Skipping 5201454623. Already sent before\n",
483 | "Skipping 1325080644. Already sent before\n",
484 | "Skipping 5963865219. Already sent before\n",
485 | "Skipping 909470906. Already sent before\n",
486 | "Failed to send message to 5619240406. Reason: Forbidden: bot was blocked by the user\n",
487 | "Skipping 5040929969. Already sent before\n",
488 | "Skipping 1452366415. Already sent before\n",
489 | "Skipping 570423019. Already sent before\n",
490 | "Skipping 1210618188. Already sent before\n",
491 | "Skipping 218983387. Already sent before\n",
492 | "Skipping 5289992694. Already sent before\n",
493 | "Skipping 6727825. Already sent before\n",
494 | "Skipping 5963491612. Already sent before\n",
495 | "Skipping 628117904. Already sent before\n",
496 | "Failed to send message to 6145382722. Reason: Forbidden: bot was blocked by the user\n",
497 | "Skipping 1269488847. Already sent before\n",
498 | "Skipping 1491755960. Already sent before\n",
499 | "Skipping 5598275766. Already sent before\n",
500 | "Skipping 5310157080. Already sent before\n",
501 | "Skipping 5611385382. Already sent before\n",
502 | "Failed to send message to 12621125. Reason: Forbidden: bot was blocked by the user\n",
503 | "Skipping 635460356. Already sent before\n",
504 | "Skipping 1447929454. Already sent before\n",
505 | "Skipping 6689999. Already sent before\n",
506 | "Failed to send message to 1624335871. Reason: Forbidden: bot was blocked by the user\n",
507 | "Skipping 5340110057. Already sent before\n",
508 | "Skipping 676057669. Already sent before\n",
509 | "Skipping 5338113807. Already sent before\n",
510 | "Skipping 1668228627. Already sent before\n",
511 | "Skipping 205663826. Already sent before\n",
512 | "Skipping 1544677735. Already sent before\n",
513 | "Skipping 5142296190. Already sent before\n",
514 | "Skipping 1589088369. Already sent before\n",
515 | "Skipping 478108016. Already sent before\n",
516 | "Skipping 975461225. Already sent before\n",
517 | "Skipping 760907844. Already sent before\n",
518 | "Skipping 1876908710. Already sent before\n",
519 | "Skipping 1526722557. Already sent before\n",
520 | "Skipping 1507911762. Already sent before\n",
521 | "Skipping 5002936898. Already sent before\n",
522 | "Skipping 9121359. Already sent before\n",
523 | "Skipping 1265565324. Already sent before\n",
524 | "Skipping 5824428956. Already sent before\n",
525 | "Failed to send message to 1768925686. Reason: Forbidden: bot was blocked by the user\n",
526 | "Skipping 714723086. Already sent before\n",
527 | "Skipping 507740243. Already sent before\n",
528 | "Skipping 1873357697. Already sent before\n",
529 | "Skipping 1165273939. Already sent before\n",
530 | "Skipping 5225973907. Already sent before\n",
531 | "Skipping 1006390195. Already sent before\n",
532 | "Skipping 980754882. Already sent before\n",
533 | "Skipping 5256356408. Already sent before\n",
534 | "Skipping 1513782906. Already sent before\n",
535 | "Skipping 5051138844. Already sent before\n",
536 | "Failed to send message to 1516697887. Reason: Forbidden: bot was blocked by the user\n",
537 | "Skipping 1112348989. Already sent before\n",
538 | "Skipping 1314138068. Already sent before\n",
539 | "Skipping 636207422. Already sent before\n",
540 | "Skipping 833109378. Already sent before\n",
541 | "Skipping 5347365175. Already sent before\n",
542 | "Skipping 5251131566. Already sent before\n",
543 | "Failed to send message to 78205988. Reason: Forbidden: bot was blocked by the user\n",
544 | "Skipping 5627299861. Already sent before\n",
545 | "Skipping 139992603. Already sent before\n",
546 | "Skipping 1758317408. Already sent before\n",
547 | "Skipping 1947512039. Already sent before\n",
548 | "Skipping 1427320680. Already sent before\n",
549 | "Skipping 6162492461. Already sent before\n",
550 | "Skipping 6160813287. Already sent before\n",
551 | "Skipping 685841021. Already sent before\n",
552 | "Skipping 1724688885. Already sent before\n",
553 | "Skipping 1381913508. Already sent before\n",
554 | "Skipping 1026637061. Already sent before\n",
555 | "Skipping 1775621120. Already sent before\n",
556 | "Skipping 1685334053. Already sent before\n",
557 | "Skipping 744362015. Already sent before\n",
558 | "Skipping 1261350396. Already sent before\n",
559 | "Skipping 1090939482. Already sent before\n",
560 | "Skipping 1240220503. Already sent before\n",
561 | "Skipping 5630559725. Already sent before\n",
562 | "Skipping 6273295038. Already sent before\n",
563 | "Skipping 961828291. Already sent before\n",
564 | "Skipping 5650110417. Already sent before\n",
565 | "Skipping 1993908691. Already sent before\n",
566 | "Skipping 1128409158. Already sent before\n",
567 | "Skipping 1734740708. Already sent before\n",
568 | "Skipping 5476099207. Already sent before\n",
569 | "Failed to send message to 1220813167. Reason: Forbidden: bot was blocked by the user\n",
570 | "Failed to send message to 477808361. Reason: Forbidden: bot was blocked by the user\n",
571 | "Skipping 971597200. Already sent before\n",
572 | "Skipping 782402861. Already sent before\n",
573 | "Skipping 1105189852. Already sent before\n",
574 | "Skipping 5294539397. Already sent before\n",
575 | "Skipping 1258088764. Already sent before\n",
576 | "Skipping 5870998119. Already sent before\n",
577 | "Skipping 5215592583. Already sent before\n",
578 | "Skipping 5404027854. Already sent before\n",
579 | "Skipping 1470815154. Already sent before\n",
580 | "Skipping 5274303658. Already sent before\n",
581 | "Skipping 214204103. Already sent before\n",
582 | "Skipping 1248946097. Already sent before\n",
583 | "Skipping 1317277037. Already sent before\n",
584 | "Skipping 457881611. Already sent before\n",
585 | "Skipping 6702683. Already sent before\n",
586 | "Skipping 1985816851. Already sent before\n",
587 | "Skipping 5043524149. Already sent before\n",
588 | "Skipping 340244939. Already sent before\n",
589 | "Skipping 1081329768. Already sent before\n",
590 | "Skipping 564692978. Already sent before\n",
591 | "Skipping 1479358111. Already sent before\n",
592 | "Skipping 1124257222. Already sent before\n",
593 | "Skipping 5411630657. Already sent before\n",
594 | "Skipping 5483680493. Already sent before\n",
595 | "Failed to send message to 1619635603. Reason: Forbidden: bot was blocked by the user\n",
596 | "Skipping 1128089796. Already sent before\n",
597 | "Skipping 1290181639. Already sent before\n",
598 | "Skipping 1988304847. Already sent before\n",
599 | "Skipping 12506044. Already sent before\n",
600 | "Skipping 876715864. Already sent before\n",
601 | "Skipping 1671053066. Already sent before\n",
602 | "Skipping 5000022227. Already sent before\n",
603 | "Skipping 1284261135. Already sent before\n",
604 | "Failed to send message to 59392620. Reason: Forbidden: bot was blocked by the user\n",
605 | "Skipping 1495675641. Already sent before\n",
606 | "Skipping 5227695553. Already sent before\n",
607 | "Skipping 998962857. Already sent before\n",
608 | "Skipping 707026508. Already sent before\n",
609 | "Skipping 981638509. Already sent before\n",
610 | "Skipping 1971826455. Already sent before\n",
611 | "Skipping 623226727. Already sent before\n",
612 | "Skipping 1250937749. Already sent before\n",
613 | "Failed to send message to 5685434844. Reason: Forbidden: bot was blocked by the user\n",
614 | "Skipping 1269367097. Already sent before\n",
615 | "Skipping 5893153616. Already sent before\n",
616 | "Skipping 1907239824. Already sent before\n",
617 | "Skipping 1398102028. Already sent before\n",
618 | "Skipping 1458420352. Already sent before\n",
619 | "Skipping 1021745738. Already sent before\n",
620 | "Skipping 1548624395. Already sent before\n",
621 | "Skipping 2122745394. Already sent before\n",
622 | "Skipping 1204713497. Already sent before\n",
623 | "Skipping 1066505431. Already sent before\n",
624 | "Skipping 1338336992. Already sent before\n",
625 | "Failed to send message to 2046941811. Reason: Forbidden: bot was blocked by the user\n",
626 | "Skipping 5577695650. Already sent before\n",
627 | "Skipping 525005282. Already sent before\n",
628 | "Skipping 1771739346. Already sent before\n",
629 | "Skipping 1418571932. Already sent before\n",
630 | "Skipping 5726094976. Already sent before\n",
631 | "Skipping 484498149. Already sent before\n",
632 | "Skipping 5039180704. Already sent before\n",
633 | "Skipping 786901982. Already sent before\n",
634 | "Skipping 1080524631. Already sent before\n",
635 | "Skipping 1025044884. Already sent before\n",
636 | "Skipping 6182792717. Already sent before\n",
637 | "Skipping 1103693554. Already sent before\n",
638 | "Skipping 932452530. Already sent before\n",
639 | "Skipping 1461485400. Already sent before\n",
640 | "Skipping 854060645. Already sent before\n",
641 | "Skipping 828351687. Already sent before\n",
642 | "Failed to send message to 5857084141. Reason: Forbidden: bot was blocked by the user\n",
643 | "Failed to send message to 727936998. Reason: Forbidden: bot was blocked by the user\n",
644 | "Skipping 5358643195. Already sent before\n",
645 | "Skipping 53975563. Already sent before\n",
646 | "Skipping 1576309413. Already sent before\n",
647 | "Skipping 552485462. Already sent before\n",
648 | "Skipping 1081370544. Already sent before\n",
649 | "Skipping 1217049157. Already sent before\n",
650 | "Skipping 804067221. Already sent before\n",
651 | "Skipping 351195750. Already sent before\n",
652 | "Skipping 1377384424. Already sent before\n",
653 | "Skipping 5476204642. Already sent before\n",
654 | "Skipping 5499622841. Already sent before\n",
655 | "Skipping 141850278. Already sent before\n",
656 | "Skipping 839042028. Already sent before\n",
657 | "Skipping 146539110. Already sent before\n",
658 | "Skipping 1420156323. Already sent before\n",
659 | "Failed to send message to 861124808. Reason: Forbidden: bot was blocked by the user\n",
660 | "Skipping 227964699. Already sent before\n",
661 | "Skipping 1489574571. Already sent before\n",
662 | "Skipping 1194973299. Already sent before\n",
663 | "Failed to send message to 5652844635. Reason: Forbidden: bot was blocked by the user\n",
664 | "Skipping 2042268056. Already sent before\n",
665 | "Skipping 5353922437. Already sent before\n",
666 | "Skipping 6043434884. Already sent before\n",
667 | "Skipping 1607932199. Already sent before\n",
668 | "Skipping 416465840. Already sent before\n",
669 | "Skipping 565304566. Already sent before\n",
670 | "Skipping 793864706. Already sent before\n",
671 | "Skipping 946476339. Already sent before\n",
672 | "Skipping 5683429757. Already sent before\n",
673 | "Skipping 272842049. Already sent before\n",
674 | "Failed to send message to 1100360597. Reason: Forbidden: bot was blocked by the user\n",
675 | "Skipping 1688686442. Already sent before\n",
676 | "Skipping 715741694. Already sent before\n",
677 | "Skipping 1729994155. Already sent before\n",
678 | "Failed to send message to 716121149. Reason: Forbidden: bot was blocked by the user\n",
679 | "Skipping 1364401849. Already sent before\n",
680 | "Skipping 218308952. Already sent before\n",
681 | "Skipping 1047561281. Already sent before\n",
682 | "Skipping 1122578192. Already sent before\n",
683 | "Skipping 1732778357. Already sent before\n",
684 | "Skipping 1040648182. Already sent before\n",
685 | "Skipping 5642370575. Already sent before\n",
686 | "Skipping 1036079699. Already sent before\n",
687 | "Skipping 1034819124. Already sent before\n",
688 | "Skipping 325526352. Already sent before\n",
689 | "Skipping 690579707. Already sent before\n",
690 | "Skipping 6254711555. Already sent before\n",
691 | "Skipping 5030813792. Already sent before\n",
692 | "Skipping 1353175907. Already sent before\n",
693 | "Skipping 1019162846. Already sent before\n",
694 | "Skipping 1020210407. Already sent before\n",
695 | "Skipping 5028707131. Already sent before\n",
696 | "Skipping 2141870723. Already sent before\n",
697 | "Skipping 5475729573. Already sent before\n",
698 | "Skipping 893211378. Already sent before\n",
699 | "Skipping 1555475497. Already sent before\n",
700 | "Skipping 1653442253. Already sent before\n",
701 | "Skipping 270780875. Already sent before\n",
702 | "Skipping 796384173. Already sent before\n",
703 | "Skipping 5775214293. Already sent before\n",
704 | "Failed to send message to 6015997429. Reason: Forbidden: bot was blocked by the user\n",
705 | "Skipping 629746102. Already sent before\n",
706 | "Skipping 920468427. Already sent before\n",
707 | "Skipping 5380453239. Already sent before\n",
708 | "Skipping 758372036. Already sent before\n",
709 | "Skipping 5809595859. Already sent before\n",
710 | "Skipping 6118383402. Already sent before\n",
711 | "Skipping 5432131203. Already sent before\n",
712 | "Skipping 505103225. Already sent before\n",
713 | "Failed to send message to 1099538870. Reason: Forbidden: bot was blocked by the user\n",
714 | "Skipping 1370306721. Already sent before\n",
715 | "Skipping 1364900733. Already sent before\n",
716 | "Skipping 1565496916. Already sent before\n",
717 | "Skipping 1684546858. Already sent before\n",
718 | "Skipping 1408152760. Already sent before\n",
719 | "Skipping 5672037025. Already sent before\n",
720 | "Skipping 1176834119. Already sent before\n",
721 | "Skipping 861802974. Already sent before\n",
722 | "Skipping 5469163503. Already sent before\n",
723 | "Skipping 1325932732. Already sent before\n",
724 | "Skipping 1196595937. Already sent before\n",
725 | "Skipping 2061669054. Already sent before\n",
726 | "Skipping 1177990383. Already sent before\n",
727 | "Skipping 5599688599. Already sent before\n",
728 | "Skipping 6069888524. Already sent before\n",
729 | "Skipping 5219639970. Already sent before\n",
730 | "Skipping 44099595. Already sent before\n",
731 | "Skipping 1101498733. Already sent before\n",
732 | "Skipping 810818321. Already sent before\n",
733 | "Skipping 5160185688. Already sent before\n",
734 | "Skipping 1511693307. Already sent before\n",
735 | "Skipping 5856354930. Already sent before\n",
736 | "Skipping 5675509854. Already sent before\n",
737 | "Skipping 1341582687. Already sent before\n",
738 | "Skipping 1323614678. Already sent before\n",
739 | "Skipping 1099073823. Already sent before\n",
740 | "Skipping 1963360964. Already sent before\n",
741 | "Skipping 6047741970. Already sent before\n",
742 | "Skipping 474933856. Already sent before\n",
743 | "Skipping 677081358. Already sent before\n",
744 | "Skipping 671498055. Already sent before\n",
745 | "Skipping 600102759. Already sent before\n",
746 | "Skipping 685898286. Already sent before\n",
747 | "Skipping 1171554430. Already sent before\n",
748 | "Skipping 859470693. Already sent before\n",
749 | "Skipping 292918071. Already sent before\n",
750 | "Skipping 16134757. Already sent before\n",
751 | "Skipping 6166364827. Already sent before\n",
752 | "Skipping 1004911331. Already sent before\n",
753 | "Skipping 1163289440. Already sent before\n",
754 | "Skipping 1694034689. Already sent before\n",
755 | "Skipping 836350139. Already sent before\n",
756 | "Skipping 1279270596. Already sent before\n",
757 | "Skipping 963637612. Already sent before\n",
758 | "Skipping 749486758. Already sent before\n",
759 | "Skipping 5463225699. Already sent before\n",
760 | "Skipping 699654968. Already sent before\n",
761 | "Skipping 5425866503. Already sent before\n",
762 | "Skipping 547659699. Already sent before\n",
763 | "Skipping 434216494. Already sent before\n",
764 | "Skipping 1579115940. Already sent before\n",
765 | "Skipping 720296100. Already sent before\n",
766 | "Skipping 5023098139. Already sent before\n",
767 | "Skipping 137536512. Already sent before\n",
768 | "Skipping 877633949. Already sent before\n",
769 | "Skipping 1650353904. Already sent before\n",
770 | "Skipping 5764417782. Already sent before\n",
771 | "Skipping 5114223141. Already sent before\n",
772 | "Failed to send message to 1150507674. Reason: Forbidden: bot was blocked by the user\n",
773 | "Skipping 1382949427. Already sent before\n",
774 | "Skipping 136145252. Already sent before\n",
775 | "Failed to send message to 5116338. Reason: Forbidden: bot was blocked by the user\n",
776 | "Skipping 1719385576. Already sent before\n",
777 | "Skipping 1146622626. Already sent before\n",
778 | "Skipping 1112305693. Already sent before\n",
779 | "Skipping 1293671896. Already sent before\n",
780 | "Skipping 1687269061. Already sent before\n",
781 | "Skipping 625588994. Already sent before\n",
782 | "Skipping 287203051. Already sent before\n",
783 | "Skipping 828555620. Already sent before\n",
784 | "Skipping 1562508618. Already sent before\n",
785 | "Skipping 7443934. Already sent before\n",
786 | "Skipping 944128239. Already sent before\n",
787 | "Skipping 5864580672. Already sent before\n",
788 | "Skipping 513254486. Already sent before\n",
789 | "Skipping 80203691. Already sent before\n",
790 | "Skipping 2008149116. Already sent before\n",
791 | "Skipping 1370539481. Already sent before\n",
792 | "Skipping 5707505724. Already sent before\n",
793 | "Skipping 782252025. Already sent before\n",
794 | "Skipping 959162254. Already sent before\n",
795 | "Skipping 755540339. Already sent before\n",
796 | "Skipping 1228376654. Already sent before\n",
797 | "Skipping 373524290. Already sent before\n",
798 | "Skipping 215310774. Already sent before\n",
799 | "Skipping 61174284. Already sent before\n",
800 | "Skipping 1197644031. Already sent before\n",
801 | "Skipping 780233633. Already sent before\n",
802 | "Skipping 1004490169. Already sent before\n",
803 | "Skipping 6204872199. Already sent before\n",
804 | "Skipping 834332055. Already sent before\n",
805 | "Skipping 11329264. Already sent before\n",
806 | "Skipping 907484916. Already sent before\n",
807 | "Skipping 1307577029. Already sent before\n",
808 | "Skipping 1064497615. Already sent before\n",
809 | "Skipping 5451978892. Already sent before\n",
810 | "Skipping 305776710. Already sent before\n",
811 | "Skipping 1674692650. Already sent before\n",
812 | "Skipping 1150018448. Already sent before\n",
813 | "Skipping 1125183744. Already sent before\n",
814 | "Skipping 4251129. Already sent before\n",
815 | "Skipping 723305584. Already sent before\n",
816 | "Skipping 5602269872. Already sent before\n",
817 | "Skipping 5545398063. Already sent before\n",
818 | "Skipping 489432545. Already sent before\n",
819 | "Skipping 536815874. Already sent before\n",
820 | "Skipping 5372284321. Already sent before\n",
821 | "Skipping 1795150018. Already sent before\n",
822 | "Skipping 1382607943. Already sent before\n",
823 | "Failed to send message to 948613713. Reason: Forbidden: bot was blocked by the user\n",
824 | "Skipping 1128490617. Already sent before\n",
825 | "Skipping 5178054377. Already sent before\n",
826 | "Skipping 289593517. Already sent before\n",
827 | "Skipping 560042032. Already sent before\n",
828 | "Skipping 314367308. Already sent before\n",
829 | "Skipping 5254267105. Already sent before\n",
830 | "Skipping 414262685. Already sent before\n",
831 | "Skipping 646770270. Already sent before\n",
832 | "Skipping 2131193082. Already sent before\n",
833 | "Skipping 898376264. Already sent before\n",
834 | "Skipping 475422642. Already sent before\n",
835 | "Skipping 279450760. Already sent before\n",
836 | "Skipping 1497304405. Already sent before\n",
837 | "Skipping 65746922. Already sent before\n",
838 | "Skipping 1578377860. Already sent before\n",
839 | "Skipping 144161659. Already sent before\n",
840 | "Skipping 383312153. Already sent before\n",
841 | "Skipping 6215057431. Already sent before\n",
842 | "Skipping 5784668204. Already sent before\n",
843 | "Skipping 1421701740. Already sent before\n",
844 | "Skipping 1008586197. Already sent before\n",
845 | "Skipping 719747831. Already sent before\n",
846 | "Skipping 1997239715. Already sent before\n",
847 | "Skipping 906511082. Already sent before\n",
848 | "Skipping 1282495147. Already sent before\n",
849 | "Skipping 5019591219. Already sent before\n",
850 | "Skipping 940688263. Already sent before\n",
851 | "Skipping 9733209. Already sent before\n",
852 | "Skipping 5616066338. Already sent before\n",
853 | "Skipping 1082682135. Already sent before\n",
854 | "Skipping 1256349477. Already sent before\n",
855 | "Skipping 1142146416. Already sent before\n",
856 | "Failed to send message to 82150541. Reason: Forbidden: bot was blocked by the user\n",
857 | "Skipping 453141970. Already sent before\n",
858 | "Skipping 1639186376. Already sent before\n",
859 | "Skipping 20832019. Already sent before\n",
860 | "Skipping 30310999. Already sent before\n",
861 | "Failed to send message to 5963958257. Reason: Forbidden: bot was blocked by the user\n",
862 | "Skipping 10005237. Already sent before\n",
863 | "Skipping 139811512. Already sent before\n",
864 | "Failed to send message to 1818756776. Reason: Forbidden: bot was kicked from the supergroup chat\n",
865 | "Skipping 394404549. Already sent before\n",
866 | "Skipping 1291815312. Already sent before\n",
867 | "Skipping 1237412942. Already sent before\n",
868 | "Skipping 35551605. Already sent before\n",
869 | "Skipping 5869687745. Already sent before\n",
870 | "Skipping 220865232. Already sent before\n",
871 | "Skipping 1038967711. Already sent before\n",
872 | "Skipping 5011981924. Already sent before\n",
873 | "Skipping 5204624904. Already sent before\n",
874 | "Skipping 1772023255. Already sent before\n",
875 | "Skipping 11380569. Already sent before\n",
876 | "Failed to send message to 1927974811. Reason: Forbidden: bot was blocked by the user\n",
877 | "Skipping 1029905212. Already sent before\n",
878 | "Skipping 835996819. Already sent before\n",
879 | "Skipping 1207503845. Already sent before\n",
880 | "Skipping 251141027. Already sent before\n",
881 | "Skipping 5213220568. Already sent before\n",
882 | "Skipping 1207484464. Already sent before\n",
883 | "Skipping 791939168. Already sent before\n",
884 | "Skipping 1910239214. Already sent before\n",
885 | "Skipping 1905291594. Already sent before\n",
886 | "Skipping 1483823297. Already sent before\n",
887 | "Skipping 211631570. Already sent before\n",
888 | "Skipping 5652819758. Already sent before\n",
889 | "Skipping 608959204. Already sent before\n",
890 | "Skipping 256342401. Already sent before\n",
891 | "Skipping 2023384969. Already sent before\n",
892 | "Skipping 759775997. Already sent before\n",
893 | "Skipping 1348049359. Already sent before\n",
894 | "Skipping 986384372. Already sent before\n",
895 | "Skipping 2116965997. Already sent before\n",
896 | "Skipping 1488474498. Already sent before\n",
897 | "Skipping 1962969957. Already sent before\n",
898 | "Skipping 739781918. Already sent before\n",
899 | "Skipping 16864838. Already sent before\n",
900 | "Skipping 903593465. Already sent before\n",
901 | "Skipping 675893550. Already sent before\n",
902 | "Skipping 1755942402. Already sent before\n",
903 | "Skipping 877359578. Already sent before\n",
904 | "Skipping 5595511096. Already sent before\n",
905 | "Skipping 801857996. Already sent before\n",
906 | "Skipping 811707135. Already sent before\n",
907 | "Skipping 361416262. Already sent before\n",
908 | "Skipping 1082595819. Already sent before\n",
909 | "Skipping 820284717. Already sent before\n",
910 | "Skipping 6109163749. Already sent before\n",
911 | "Failed to send message to 1719358561. Reason: Forbidden: bot was kicked from the supergroup chat\n",
912 | "Skipping 16420611. Already sent before\n",
913 | "Skipping 13002777. Already sent before\n",
914 | "Skipping 383292068. Already sent before\n",
915 | "Skipping 645262734. Already sent before\n",
916 | "Skipping 5342070652. Already sent before\n",
917 | "Skipping 1307986166. Already sent before\n",
918 | "Skipping 383460784. Already sent before\n",
919 | "Skipping 1662242250. Already sent before\n",
920 | "Skipping 1913326597. Already sent before\n",
921 | "Skipping 846251418. Already sent before\n",
922 | "Failed to send message to 719450670. Reason: Forbidden: bot was blocked by the user\n",
923 | "Failed to send message to 650260973. Reason: Forbidden: bot was blocked by the user\n",
924 | "Skipping 618521035. Already sent before\n",
925 | "Skipping 1176795624. Already sent before\n",
926 | "Skipping 419292265. Already sent before\n",
927 | "Skipping 6763340. Already sent before\n",
928 | "Skipping 1542686256. Already sent before\n",
929 | "Skipping 5184461645. Already sent before\n",
930 | "Skipping 510792742. Already sent before\n",
931 | "Skipping 35163779. Already sent before\n",
932 | "Skipping 547091675. Already sent before\n",
933 | "Skipping 157816900. Already sent before\n",
934 | "Skipping 5106348701. Already sent before\n",
935 | "Skipping 310368992. Already sent before\n",
936 | "Skipping 433882230. Already sent before\n",
937 | "Skipping 5347454992. Already sent before\n",
938 | "Skipping 1339741631. Already sent before\n",
939 | "Skipping 5109279801. Already sent before\n",
940 | "Skipping 1431139817. Already sent before\n",
941 | "Skipping 958335447. Already sent before\n",
942 | "Skipping 617504186. Already sent before\n",
943 | "Skipping 104853593. Already sent before\n",
944 | "Skipping 487542159. Already sent before\n",
945 | "Skipping 702852201. Already sent before\n",
946 | "Skipping 5849720779. Already sent before\n",
947 | "Skipping 980653368. Already sent before\n",
948 | "Skipping 823624414. Already sent before\n",
949 | "Skipping 1132673149. Already sent before\n",
950 | "Skipping 988140508. Already sent before\n",
951 | "Skipping 1303466912. Already sent before\n",
952 | "Skipping 1589607692. Already sent before\n",
953 | "Skipping 211027264. Already sent before\n",
954 | "Skipping 6676467. Already sent before\n",
955 | "Skipping 916568707. Already sent before\n",
956 | "Skipping 1305373285. Already sent before\n",
957 | "Skipping 905339971. Already sent before\n",
958 | "Skipping 1744960678. Already sent before\n",
959 | "Skipping 995540842. Already sent before\n",
960 | "Skipping 5052801576. Already sent before\n",
961 | "Skipping 850270735. Already sent before\n",
962 | "Skipping 1600660917. Already sent before\n",
963 | "Skipping 1055686443. Already sent before\n",
964 | "Skipping 1077826365. Already sent before\n",
965 | "Skipping 387563935. Already sent before\n",
966 | "Skipping 305123432. Already sent before\n",
967 | "Skipping 5052289151. Already sent before\n",
968 | "Skipping 900292911. Already sent before\n",
969 | "Failed to send message to 429225873. Reason: Forbidden: bot was blocked by the user\n",
970 | "Failed to send message to 977529467. Reason: Forbidden: bot was blocked by the user\n",
971 | "Skipping 692884004. Already sent before\n",
972 | "Skipping 439524497. Already sent before\n",
973 | "Skipping 6004753. Already sent before\n",
974 | "Skipping 5171433704. Already sent before\n",
975 | "Skipping 1016745939. Already sent before\n",
976 | "Skipping 5010161131. Already sent before\n",
977 | "Skipping 2093747407. Already sent before\n",
978 | "Skipping 1539078557. Already sent before\n",
979 | "Skipping 601806588. Already sent before\n",
980 | "Skipping 1007302763. Already sent before\n",
981 | "Skipping 948625701. Already sent before\n",
982 | "Skipping 732512421. Already sent before\n",
983 | "Failed to send message to 170903171. Reason: Forbidden: bot was blocked by the user\n",
984 | "Skipping 486321120. Already sent before\n",
985 | "Skipping 699798930. Already sent before\n",
986 | "Skipping 1367406431. Already sent before\n",
987 | "Skipping 5165047473. Already sent before\n",
988 | "Skipping 177194518. Already sent before\n",
989 | "Skipping 615479238. Already sent before\n",
990 | "Skipping 893132495. Already sent before\n",
991 | "Skipping 2034776819. Already sent before\n",
992 | "Skipping 1208555035. Already sent before\n",
993 | "Skipping 5237350570. Already sent before\n",
994 | "Skipping 400346337. Already sent before\n",
995 | "Skipping 1561148633. Already sent before\n",
996 | "Skipping 929919979. Already sent before\n",
997 | "Skipping 1933684572. Already sent before\n",
998 | "Skipping 1226493096. Already sent before\n",
999 | "Skipping 620195365. Already sent before\n",
1000 | "Skipping 1315054594. Already sent before\n",
1001 | "Skipping 5155931222. Already sent before\n",
1002 | "Skipping 9250257. Already sent before\n",
1003 | "Skipping 5860300204. Already sent before\n",
1004 | "Skipping 1148232261. Already sent before\n",
1005 | "Skipping 5303887200. Already sent before\n",
1006 | "Skipping 6282570587. Already sent before\n",
1007 | "Skipping 1707660826. Already sent before\n",
1008 | "Skipping 516751375. Already sent before\n",
1009 | "Skipping 100822102. Already sent before\n",
1010 | "Skipping 1028001176. Already sent before\n",
1011 | "Skipping 5237954659. Already sent before\n",
1012 | "Skipping 642999. Already sent before\n",
1013 | "Skipping 7501132. Already sent before\n",
1014 | "Skipping 1383085335. Already sent before\n",
1015 | "Skipping 1287610940. Already sent before\n",
1016 | "Skipping 5013420256. Already sent before\n",
1017 | "Skipping 725099806. Already sent before\n",
1018 | "Skipping 773488815. Already sent before\n",
1019 | "Skipping 1202825646. Already sent before\n",
1020 | "Skipping 1019814806. Already sent before\n",
1021 | "Skipping 784676583. Already sent before\n",
1022 | "Skipping 5438700779. Already sent before\n",
1023 | "Skipping 611624673. Already sent before\n",
1024 | "Skipping 1531023691. Already sent before\n",
1025 | "Skipping 5524057122. Already sent before\n",
1026 | "Skipping 516322093. Already sent before\n",
1027 | "Skipping 1290955552. Already sent before\n",
1028 | "Skipping 1761052018. Already sent before\n",
1029 | "Skipping 558974410. Already sent before\n",
1030 | "Skipping 5977977408. Already sent before\n",
1031 | "Skipping 3288449. Already sent before\n",
1032 | "Skipping 1513024753. Already sent before\n",
1033 | "Skipping 912062262. Already sent before\n",
1034 | "Skipping 6182533281. Already sent before\n",
1035 | "Skipping 792843693. Already sent before\n",
1036 | "Skipping 5595139019. Already sent before\n",
1037 | "Skipping 14918783. Already sent before\n",
1038 | "Skipping 5961338669. Already sent before\n",
1039 | "Skipping 1251945897. Already sent before\n",
1040 | "Skipping 721321614. Already sent before\n",
1041 | "Skipping 1233332156. Already sent before\n",
1042 | "Skipping 195228465. Already sent before\n",
1043 | "Skipping 9508927. Already sent before\n",
1044 | "Skipping 975053335. Already sent before\n",
1045 | "Skipping 1392897532. Already sent before\n",
1046 | "Skipping 676034635. Already sent before\n",
1047 | "Skipping 820041498. Already sent before\n",
1048 | "Skipping 7203424. Already sent before\n",
1049 | "Skipping 1094061541. Already sent before\n",
1050 | "Skipping 339320726. Already sent before\n",
1051 | "Skipping 923604744. Already sent before\n",
1052 | "Skipping 6406622. Already sent before\n",
1053 | "Skipping 76717614. Already sent before\n",
1054 | "Skipping 414318778. Already sent before\n",
1055 | "Failed to send message to 2104720788. Reason: Forbidden: bot was blocked by the user\n",
1056 | "Skipping 1225215131. Already sent before\n",
1057 | "Skipping 7191211. Already sent before\n",
1058 | "Skipping 937834211. Already sent before\n",
1059 | "Skipping 165369124. Already sent before\n",
1060 | "Skipping 878671814. Already sent before\n",
1061 | "Skipping 5474097719. Already sent before\n",
1062 | "Skipping 169283175. Already sent before\n",
1063 | "Failed to send message to 196987793. Reason: Forbidden: bot was blocked by the user\n",
1064 | "Failed to send message to 2042927462. Reason: Forbidden: bot was blocked by the user\n",
1065 | "Failed to send message to 1394492009. Reason: Forbidden: bot was blocked by the user\n",
1066 | "Skipping 15822909. Already sent before\n",
1067 | "Skipping 5315620938. Already sent before\n",
1068 | "Skipping 1401698182. Already sent before\n",
1069 | "Skipping 5840857302. Already sent before\n",
1070 | "Skipping 17513864. Already sent before\n",
1071 | "Skipping 479746418. Already sent before\n",
1072 | "Skipping 1717964847. Already sent before\n",
1073 | "Failed to send message to 6053675632. Reason: Forbidden: bot was blocked by the user\n",
1074 | "Skipping 5683576132. Already sent before\n",
1075 | "Skipping 172954615. Already sent before\n",
1076 | "Skipping 6004449635. Already sent before\n",
1077 | "Skipping 5424836. Already sent before\n",
1078 | "Skipping 921683433. Already sent before\n",
1079 | "Failed to send message to 532018058. Reason: Forbidden: bot was blocked by the user\n",
1080 | "Skipping 6138424948. Already sent before\n",
1081 | "Skipping 6024723587. Already sent before\n",
1082 | "Skipping 6208113372. Already sent before\n",
1083 | "Skipping 373674229. Already sent before\n",
1084 | "Skipping 223212754. Already sent before\n",
1085 | "Skipping 611959785. Already sent before\n",
1086 | "Skipping 902209336. Already sent before\n",
1087 | "Skipping 172199844. Already sent before\n",
1088 | "Skipping 268745615. Already sent before\n",
1089 | "Skipping 101040390. Already sent before\n",
1090 | "Skipping 5767669442. Already sent before\n",
1091 | "Skipping 334277655. Already sent before\n",
1092 | "Skipping 585088972. Already sent before\n",
1093 | "Skipping 416077141. Already sent before\n",
1094 | "Skipping 1710197192. Already sent before\n",
1095 | "Skipping 1774024623. Already sent before\n",
1096 | "Skipping 2101971630. Already sent before\n",
1097 | "Skipping 5635727535. Already sent before\n",
1098 | "Skipping 6224860345. Already sent before\n",
1099 | "Skipping 262890648. Already sent before\n",
1100 | "Skipping 5936754668. Already sent before\n",
1101 | "Skipping 154065947. Already sent before\n",
1102 | "Skipping 211411316. Already sent before\n",
1103 | "Skipping 6895076. Already sent before\n",
1104 | "Skipping 2032540047. Already sent before\n",
1105 | "Skipping 974581497. Already sent before\n",
1106 | "Skipping 7611179. Already sent before\n",
1107 | "Skipping 663694558. Already sent before\n",
1108 | "Skipping 5224294137. Already sent before\n",
1109 | "Skipping 669949464. Already sent before\n",
1110 | "Skipping 14331534. Already sent before\n",
1111 | "Skipping 400070146. Already sent before\n",
1112 | "Skipping 688826120. Already sent before\n",
1113 | "Skipping 273524979. Already sent before\n",
1114 | "Skipping 14319452. Already sent before\n",
1115 | "Skipping 5472244651. Already sent before\n",
1116 | "Skipping 8957314. Already sent before\n",
1117 | "Skipping 388894933. Already sent before\n",
1118 | "Skipping 160383568. Already sent before\n",
1119 | "Skipping 6259538740. Already sent before\n",
1120 | "Skipping 673777152. Already sent before\n",
1121 | "Skipping 711826444. Already sent before\n",
1122 | "Skipping 5491390831. Already sent before\n",
1123 | "Successfully sent to 717986718\n",
1124 | "Successfully sent to 5454700173\n",
1125 | "Successfully sent to 5936581021\n",
1126 | "Successfully sent to 517163947\n",
1127 | "Successfully sent to 27731830\n",
1128 | "Successfully sent to 558770900\n",
1129 | "Successfully sent to 1650748027\n",
1130 | "Successfully sent to 684044480\n",
1131 | "Successfully sent to 1175785358\n",
1132 | "Successfully sent to 599537085\n",
1133 | "Successfully sent to 264332148\n",
1134 | "Successfully sent to 361152162\n",
1135 | "Successfully sent to 1159783046\n",
1136 | "Successfully sent to 1131049810\n",
1137 | "Successfully sent to 879808951\n",
1138 | "Successfully sent to 1066546727\n",
1139 | "Successfully sent to 6038391975\n",
1140 | "Successfully sent to 265355592\n",
1141 | "Successfully sent to 5672707908\n",
1142 | "Successfully sent to 951618557\n",
1143 | "Successfully sent to 228157375\n",
1144 | "Successfully sent to 5880299765\n",
1145 | "Successfully sent to 49634669\n",
1146 | "Successfully sent to 428421888\n",
1147 | "Successfully sent to 292098802\n",
1148 | "Successfully sent to 1064609232\n",
1149 | "Successfully sent to 942844633\n",
1150 | "Successfully sent to 5302642514\n",
1151 | "Successfully sent to 322106649\n",
1152 | "Successfully sent to 968143934\n"
1153 | ]
1154 | }
1155 | ],
1156 | "source": [
1157 | "for user_dict in user_dicts: \n",
1158 | " if user_dict[\"_id\"] in already_sent_to_user_ids:\n",
1159 | " print(f\"Skipping {user_dict['_id']}. Already sent before\")\n",
1160 | " continue\n",
1161 | " \n",
1162 | " text = \"🟢 We're alive again!\\n\\n\"\n",
1163 | " text += \"Today bot sometimes didn't respond due to OpenAI outages. Now everything works fine, let's chat!\"\n",
1164 | " \n",
1165 | " try:\n",
1166 | " await application.bot.send_message(\n",
1167 | " user_dict['chat_id'],\n",
1168 | " text,\n",
1169 | " disable_web_page_preview=True,\n",
1170 | " parse_mode=ParseMode.HTML\n",
1171 | " )\n",
1172 | " print(f\"Successfully sent to {user_dict['_id']}\")\n",
1173 | " \n",
1174 | " db.add_user_to_newsletter(newsletter_id, user_dict[\"_id\"])\n",
1175 | " \n",
1176 | " time.sleep(10)\n",
1177 | " except Exception as e:\n",
1178 | " print(f\"Failed to send message to {user_dict['_id']}. Reason: {e}\")"
1179 | ]
1180 | },
1181 | {
1182 | "cell_type": "code",
1183 | "execution_count": null,
1184 | "id": "ee423e99",
1185 | "metadata": {},
1186 | "outputs": [],
1187 | "source": []
1188 | }
1189 | ],
1190 | "metadata": {
1191 | "kernelspec": {
1192 | "display_name": "Python 3 (ipykernel)",
1193 | "language": "python",
1194 | "name": "python3"
1195 | },
1196 | "language_info": {
1197 | "codemirror_mode": {
1198 | "name": "ipython",
1199 | "version": 3
1200 | },
1201 | "file_extension": ".py",
1202 | "mimetype": "text/x-python",
1203 | "name": "python",
1204 | "nbconvert_exporter": "python",
1205 | "pygments_lexer": "ipython3",
1206 | "version": "3.8.16"
1207 | }
1208 | },
1209 | "nbformat": 4,
1210 | "nbformat_minor": 5
1211 | }
1212 |
--------------------------------------------------------------------------------