pkscreener 0.46.20250210.703__cp312-cp312-manylinux2014_x86_64.whl → 0.46.20250213.705__cp312-cp312-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/README.txt +9 -7
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/MarketMonitor.py +80 -33
- pkscreener-0.46.20250213.705.data/purelib/pkscreener/classes/__init__.py +1 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/globals.py +6 -3
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/pkscreenerbot.py +285 -210
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/requirements.txt +1 -1
- {pkscreener-0.46.20250210.703.dist-info → pkscreener-0.46.20250213.705.dist-info}/METADATA +12 -10
- pkscreener-0.46.20250213.705.dist-info/RECORD +58 -0
- pkscreener-0.46.20250210.703.data/purelib/pkscreener/classes/__init__.py +0 -1
- pkscreener-0.46.20250210.703.dist-info/RECORD +0 -58
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/Disclaimer.txt +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/LICENSE-Others.txt +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/LICENSE.txt +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/LogoWM.txt +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/__init__.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/ArtTexts.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/AssetsManager.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Backtest.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Barometer.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/BaseScreeningStatistics.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/CandlePatterns.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Changelog.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/ConfigManager.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/ConsoleMenuUtility.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/ConsoleUtility.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Fetcher.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/GlobalStore.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/ImageUtility.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/MarketStatus.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/MenuOptions.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Messenger.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/OtaUpdater.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKAnalytics.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKDataService.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKDemoHandler.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKMarketOpenCloseAnalyser.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKPremiumHandler.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKScanRunner.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKScheduledTaskProgress.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKScheduler.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKSpreadsheets.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKTask.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PKUserRegistration.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Pktalib.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Portfolio.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/PortfolioXRay.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/ScreeningStatistics.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/StockScreener.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/StockSentiment.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/UserMenuChoicesHandler.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/Utility.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/WorkflowManager.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/classes/keys.py +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/courbd.ttf +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/pkscreener.ini +0 -0
- {pkscreener-0.46.20250210.703.data → pkscreener-0.46.20250213.705.data}/purelib/pkscreener/pkscreenercli.py +0 -0
- {pkscreener-0.46.20250210.703.dist-info → pkscreener-0.46.20250213.705.dist-info}/LICENSE +0 -0
- {pkscreener-0.46.20250210.703.dist-info → pkscreener-0.46.20250213.705.dist-info}/WHEEL +0 -0
- {pkscreener-0.46.20250210.703.dist-info → pkscreener-0.46.20250213.705.dist-info}/entry_points.txt +0 -0
- {pkscreener-0.46.20250210.703.dist-info → pkscreener-0.46.20250213.705.dist-info}/top_level.txt +0 -0
@@ -102,6 +102,12 @@ from telegram.ext import (
|
|
102
102
|
Filters,
|
103
103
|
CallbackContext
|
104
104
|
)
|
105
|
+
from PKDevTools.classes.Singleton import SingletonType, SingletonMixin
|
106
|
+
|
107
|
+
class PKLocalCache(SingletonMixin, metaclass=SingletonType):
|
108
|
+
def __init__(self):
|
109
|
+
super(PKLocalCache, self).__init__()
|
110
|
+
self.registeredIDs = []
|
105
111
|
|
106
112
|
# Enable logging
|
107
113
|
logging.basicConfig(
|
@@ -137,6 +143,8 @@ _updater = None
|
|
137
143
|
|
138
144
|
TOP_LEVEL_SCANNER_MENUS = ["X", "B", "MI","DV", "P"] #
|
139
145
|
TOP_LEVEL_SCANNER_SKIP_MENUS = ["M", "S", "F", "G", "C", "T", "D", "I", "E", "U", "L", "Z", "P"] # Last item will be skipped.
|
146
|
+
TOP_LEVEL_MARKUP_SKIP_MENUS = TOP_LEVEL_SCANNER_SKIP_MENUS[:len(TOP_LEVEL_SCANNER_SKIP_MENUS)-1]
|
147
|
+
TOP_LEVEL_MARKUP_SKIP_MENUS.extend(["X","P","B"])
|
140
148
|
INDEX_SKIP_MENUS_1_To_4 = ["W","E","M","Z","0","5","6","7","8","9","10","11","12","13","14","S","15"]
|
141
149
|
INDEX_SKIP_MENUS_5_TO_9 = ["W","E","M","Z","N","0","1","2","3","4","10","11","12","13","14","S","15"]
|
142
150
|
INDEX_SKIP_MENUS_10_TO_15 = ["W","E","M","Z","N","0","1","2","3","4","5","6","7","8","9","S"]
|
@@ -158,6 +166,21 @@ PIPED_SCAN_SKIP_INDEX_MENUS =["W","N","E","S","0","Z","M","15"]
|
|
158
166
|
UNSUPPORTED_COMMAND_MENUS =["22","M","Z","0",str(MAX_MENU_OPTION)]
|
159
167
|
SUPPORTED_COMMAND_MENUS = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45"]
|
160
168
|
|
169
|
+
def registerUser(user,forceFetch=False):
|
170
|
+
otpValue, subsModel,subsValidity,alertUser = 0,0,None,None
|
171
|
+
if user is not None and (user.id not in PKLocalCache().registeredIDs or forceFetch):
|
172
|
+
dbManager = DBManager()
|
173
|
+
otpValue, subsModel,subsValidity,alertUser = dbManager.getOTP(user.id,user.username,f"{user.first_name} {user.last_name}",validityIntervalInSeconds=configManager.otpInterval)
|
174
|
+
if str(otpValue).strip() != '0' and user.id not in PKLocalCache().registeredIDs:
|
175
|
+
PKLocalCache().registeredIDs.append(alertUser.userid)
|
176
|
+
return otpValue, subsModel,subsValidity,alertUser
|
177
|
+
|
178
|
+
def loadRegisteredUsers():
|
179
|
+
dbManager = DBManager()
|
180
|
+
users = dbManager.getUsers(fieldName="userid")
|
181
|
+
userIDs = [user.userid for user in users]
|
182
|
+
PKLocalCache().registeredIDs.extend(userIDs)
|
183
|
+
|
161
184
|
def initializeIntradayTimer():
|
162
185
|
try:
|
163
186
|
if (not PKDateUtilities.isTodayHoliday()[0]):
|
@@ -249,65 +272,17 @@ def matchUTR(update: Update, context: CallbackContext) -> str:
|
|
249
272
|
updatedResults = "We could not find any transaction details with the provided UTR.\nUPI transaction reference number is a 12-digit alphanumeric/numeric code that serves as a unique identifier for transactions. It is also known as the Unique Transaction Reference (UTR) number.\nYou can find your UPI reference number in the UPI-enabled app you used to make the transaction.\nFor example, you can find your UPI reference number in the History section of Google Pay. \nIn the Paytm app, you can find it by clicking View Details.\n\nIf you still cannot find it, please drop a message with transaction details/snapshot to @ItsOnlyPK to enable subscription."
|
250
273
|
else:
|
251
274
|
updatedResults = "Did you forget to include the UTR number with /Check ?\nYou should use it like this:\n\n/Check UTR_Here\n\nUPI transaction reference number is a 12-digit alphanumeric/numeric code that serves as a unique identifier for transactions. It is also known as the Unique Transaction Reference (UTR) number.\nYou can find your UPI reference number in the UPI-enabled app you used to make the transaction.\nFor example, you can find your UPI reference number in the History section of Google Pay. \nIn the Paytm app, you can find it by clicking View Details.\n\nIf you still cannot find it, please drop a message with transaction details/snapshot to @ItsOnlyPK to enable subscription."
|
252
|
-
update.message.reply_text(sanitiseTexts(updatedResults), parse_mode="HTML")
|
275
|
+
update.message.reply_text(sanitiseTexts(updatedResults), reply_markup=default_markup(user=user),parse_mode="HTML")
|
253
276
|
shareUpdateWithChannel(update=update, context=context, optionChoices=f"/otp\n{updatedResults}")
|
254
277
|
return START_ROUTES
|
255
278
|
|
256
|
-
def
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
return
|
261
|
-
else:
|
262
|
-
if update.callback_query is not None:
|
263
|
-
updateCarrier = update.callback_query
|
264
|
-
if update.message is not None:
|
265
|
-
updateCarrier = update.message
|
266
|
-
if updateCarrier is None:
|
267
|
-
return
|
268
|
-
# Get user that sent /start and log his name
|
269
|
-
user = updateCarrier.from_user
|
270
|
-
logger.info("User %s started the conversation.", user.first_name)
|
271
|
-
if not bot_available:
|
272
|
-
# Sometimes, either the payment does not go through or
|
273
|
-
# it takes time to process the last month's payment if
|
274
|
-
# done in the past 24 hours while the last date was today.
|
275
|
-
# If that happens, we won't be able to run bots or scanners
|
276
|
-
# without incurring heavy charges. Let's run in the
|
277
|
-
# unavailable mode instead until this gets fixed.
|
278
|
-
updatedResults = APOLOGY_TEXT
|
279
|
-
|
280
|
-
if bot_available:
|
281
|
-
try:
|
282
|
-
otpValue = 0
|
283
|
-
dbManager = DBManager()
|
284
|
-
otpValue, subsModel,subsValidity = dbManager.getOTP(user.id,user.username,f"{user.first_name} {user.last_name}",validityIntervalInSeconds=configManager.otpInterval)
|
285
|
-
except Exception as e: # pragma: no cover
|
286
|
-
logger.error(e)
|
287
|
-
pass
|
288
|
-
userText = f"\nUserID: <b>{user.id}</b>"
|
289
|
-
try:
|
290
|
-
subscriptionModelNames = "\n<pre>Following basic and premium subscription models are available. Premium subscription allows for unlimited premium scans:\n"
|
291
|
-
for name,value in PKUserSusbscriptions().subscriptionKeyValuePairs.items():
|
292
|
-
if name == PKSubscriptionModel.No_Subscription.name:
|
293
|
-
subscriptionModelNames = f"{subscriptionModelNames}\n{name} : ₹ {value} (Only Basic Scans are free)\n"
|
294
|
-
else:
|
295
|
-
subscriptionModelNames = f"{subscriptionModelNames}\n{name.ljust(15)} : ₹ {value}"
|
296
|
-
subscriptionModelNames = f"{subscriptionModelNames}</pre>\nPlease pay to subscribe:\n\n1. Using UPI(India) to <b>PKScreener@APL</b> \nor\n2. Proudly <b>sponsor</b>: https://github.com/sponsors/pkjmesra?frequency=recurring&sponsor=pkjmesra\n\nPlease drop a message to @ItsOnlyPK on Telegram after paying to enable subscription manually or use \n\n/check UPI_UTR_HERE_After_Making_Payment to share transaction reference number to automatically enable subscription after making payment via UPI\n!"
|
279
|
+
def editMessageText(query,editedText,reply_markup):
|
280
|
+
editedText = f"{PKDateUtilities.currentDateTime()}:\n{editedText}"
|
281
|
+
if query is not None and hasattr(query, "edit_message_text"):
|
282
|
+
query.edit_message_text(text=editedText, reply_markup=reply_markup,parse_mode="HTML")
|
297
283
|
|
298
|
-
|
299
|
-
|
300
|
-
subscriptionModelName = f"{subscriptionModelName} (Expires on: {subsValidity})"
|
301
|
-
except Exception as e:
|
302
|
-
logger.error(e)
|
303
|
-
subscriptionModelName = PKSubscriptionModel.No_Subscription.name
|
304
|
-
pass
|
305
|
-
if otpValue == 0:
|
306
|
-
updatedResults = f"We are having difficulty generating OTP for your {userText}. Please try again later."
|
307
|
-
else:
|
308
|
-
updatedResults = f"Please use your {userText} \nwith the following OTP to login to PKScreener:\n<b>{otpValue}</b>\n\nYour current subscription : <b>{subscriptionModelName}</b>. {subscriptionModelNames}"
|
309
|
-
update.message.reply_text(sanitiseTexts(updatedResults), parse_mode="HTML")
|
310
|
-
shareUpdateWithChannel(update=update, context=context, optionChoices=f"/otp\n{updatedResults}")
|
284
|
+
def otp(update: Update, context: CallbackContext) -> str:
|
285
|
+
viewSubscriptionOptions(update,context,sendOTP=True)
|
311
286
|
return START_ROUTES
|
312
287
|
|
313
288
|
def start(update: Update, context: CallbackContext, updatedResults=None, monitorIndex=0,chosenBotMenuOption="") -> str:
|
@@ -339,32 +314,7 @@ def start(update: Update, context: CallbackContext, updatedResults=None, monitor
|
|
339
314
|
# The keyboard is a list of button rows, where each row is in turn
|
340
315
|
# a list (hence `[[...]]`).
|
341
316
|
if bot_available:
|
342
|
-
|
343
|
-
if (PKDateUtilities.isTradingTime() and not PKDateUtilities.isTodayHoliday()[0]) or ("PKDevTools_Default_Log_Level" in os.environ.keys()) or sys.argv[0].endswith(".py"):
|
344
|
-
mns.append(menu().create(f"MI_{monitorIndex}", "👩💻 🚀 Intraday Monitor", 2))
|
345
|
-
if user.username == OWNER_USER:
|
346
|
-
mns.append(menu().create(f"DV_0", ("✅ Enable Logging" if not configManager.logsEnabled else "🚫 Disable Logging"), 2))
|
347
|
-
mns.append(menu().create(f"DV_1", "🔄 Restart Bot", 2))
|
348
|
-
|
349
|
-
inlineMenus = []
|
350
|
-
keyboard = []
|
351
|
-
rowIndex = 0
|
352
|
-
iconDict = {"X":"🕵️♂️ 🔍 ","B":"📈 🎯 ","P":"🧨 💥 ","MI":"","DV":""}
|
353
|
-
for mnu in mns:
|
354
|
-
if mnu.menuKey[0:2] in TOP_LEVEL_SCANNER_MENUS:
|
355
|
-
rowIndex +=1
|
356
|
-
inlineMenus.append(
|
357
|
-
InlineKeyboardButton(
|
358
|
-
iconDict.get(str(mnu.menuKey[0:2])) + mnu.menuText.split("(")[0],
|
359
|
-
callback_data="C" + str(mnu.menuKey),
|
360
|
-
)
|
361
|
-
)
|
362
|
-
if rowIndex % 2 == 0:
|
363
|
-
keyboard.append(inlineMenus)
|
364
|
-
inlineMenus = []
|
365
|
-
if len(inlineMenus) > 0:
|
366
|
-
keyboard.append(inlineMenus)
|
367
|
-
reply_markup = InlineKeyboardMarkup(keyboard)
|
317
|
+
reply_markup = default_markup(user=user,monitorIndex=monitorIndex)
|
368
318
|
cmds = m0.renderForMenu(
|
369
319
|
selectedMenu=None,
|
370
320
|
skip=TOP_LEVEL_SCANNER_SKIP_MENUS[:len(TOP_LEVEL_SCANNER_SKIP_MENUS)-1],
|
@@ -375,22 +325,23 @@ def start(update: Update, context: CallbackContext, updatedResults=None, monitor
|
|
375
325
|
reply_markup = None
|
376
326
|
|
377
327
|
if updatedResults is None:
|
378
|
-
cmdText = "\n/otp
|
328
|
+
cmdText = "\n/otp : To generate an OTP to login to PKScreener desktop console\n/check UPI_UTR_HERE_After_Making_Payment : To share transaction reference number to automatically enable subscription after making payment via UPI\n"
|
379
329
|
for cmd in cmds:
|
380
|
-
|
381
|
-
|
382
|
-
|
330
|
+
if cmd.menuKey not in TOP_LEVEL_MARKUP_SKIP_MENUS:
|
331
|
+
cmdText = f"{cmdText}\n{cmd.commandTextKey()} : {cmd.commandTextLabel()}"
|
332
|
+
tosDisclaimerText = "By using this Software, you agree to\n[+] having read through the <a href='https://pkjmesra.github.io/PKScreener/Disclaimer.txt'>Disclaimer</a>\n[+] and accept <a href='https://pkjmesra.github.io/PKScreener/tos.txt'>Terms Of Service</a> of PKScreener.\n[+] If that is not the case, you MUST immediately terminate using PKScreener and exit now!\n"
|
333
|
+
menuText = f"Welcome {user.first_name}, {(user.username)}!\n{tosDisclaimerText}Please choose a menu option by selecting a button from below.{cmdText}"
|
383
334
|
try:
|
384
335
|
if updateCarrier is not None and hasattr(updateCarrier, "data") and updateCarrier.data is not None and updateCarrier.data == "CP":
|
385
|
-
menuText = f"Piped Scanners are available using /P . Click on this /P to begin using piped scanners. To use other scanners, choose a menu option by selecting a button from below.\n
|
336
|
+
menuText = f"Piped Scanners are available using /P . Click on this /P to begin using piped scanners. To use other scanners, choose a menu option by selecting a button from below.\n{cmdText}"
|
386
337
|
except Exception as e: # pragma: no cover
|
387
338
|
logger.error(e)
|
388
339
|
pass
|
389
|
-
menuText = f"{menuText}\
|
340
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session."
|
390
341
|
else:
|
391
342
|
if not isUserSubscribed(user):
|
392
|
-
updatedResults = f"Thank you for choosing Intraday Monitor!\n\nThis scan request is, however
|
393
|
-
updatedResults = f"{updatedResults}\
|
343
|
+
updatedResults = f"Thank you for choosing Intraday Monitor!\n\nThis scan request is, however, protected and is only available to premium subscribers. It seems like you are not subscribed to the paid/premium subscription to PKScreener.\nPlease checkout all premium options by sending out a request:\n/OTP\n\nFor basic/unpaid users, you can try out the following:\n/X_0 StockCode1,StockCode2,etc.\n/X_N\n/X_1"
|
344
|
+
updatedResults = f"{updatedResults}\nClick /start if you want to restart the session."
|
394
345
|
chosenBotMenuOption = f"{chosenBotMenuOption}\nInt. Monitor. MonitorIndex:{monitorIndex}\n{updatedResults}"
|
395
346
|
menuText = updatedResults
|
396
347
|
# Send message with text and appended InlineKeyboard
|
@@ -402,6 +353,7 @@ def start(update: Update, context: CallbackContext, updatedResults=None, monitor
|
|
402
353
|
update.message.reply_text(
|
403
354
|
sanitiseTexts(menuText),
|
404
355
|
reply_markup=reply_markup,
|
356
|
+
parse_mode="HTML"
|
405
357
|
)
|
406
358
|
if Channel_Id is not None and len(str(Channel_Id)) > 0:
|
407
359
|
context.bot.send_message(
|
@@ -409,7 +361,7 @@ def start(update: Update, context: CallbackContext, updatedResults=None, monitor
|
|
409
361
|
text=f"Name: {user.first_name}, Username:@{user.username} with ID: {str(user.id)} started using the bot!\n{chosenBotMenuOption}",
|
410
362
|
parse_mode="HTML",
|
411
363
|
)
|
412
|
-
|
364
|
+
registerUser(user)
|
413
365
|
# Tell ConversationHandler that we're in state `FIRST` now
|
414
366
|
return START_ROUTES
|
415
367
|
|
@@ -583,11 +535,74 @@ def PScanners(update: Update, context: CallbackContext) -> str:
|
|
583
535
|
)
|
584
536
|
keyboard = [inlineMenus]
|
585
537
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
586
|
-
if
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
538
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session."
|
539
|
+
editMessageText(query=query,editedText=menuText,reply_markup=reply_markup)
|
540
|
+
registerUser(user)
|
541
|
+
return START_ROUTES
|
542
|
+
|
543
|
+
def viewSubscriptionOptions(update:Update,context:CallbackContext,sendOTP=False):
|
544
|
+
global bot_available
|
545
|
+
updateCarrier = None
|
546
|
+
updatedResults= ""
|
547
|
+
if update is None:
|
548
|
+
return
|
549
|
+
else:
|
550
|
+
if update.callback_query is not None:
|
551
|
+
updateCarrier = update.callback_query
|
552
|
+
if update.message is not None:
|
553
|
+
updateCarrier = update.message
|
554
|
+
if updateCarrier is None:
|
555
|
+
return
|
556
|
+
# Get user that sent /start and log his name
|
557
|
+
user = updateCarrier.from_user
|
558
|
+
logger.info("User %s started the conversation.", user.first_name)
|
559
|
+
if not bot_available:
|
560
|
+
# Sometimes, either the payment does not go through or
|
561
|
+
# it takes time to process the last month's payment if
|
562
|
+
# done in the past 24 hours while the last date was today.
|
563
|
+
# If that happens, we won't be able to run bots or scanners
|
564
|
+
# without incurring heavy charges. Let's run in the
|
565
|
+
# unavailable mode instead until this gets fixed.
|
566
|
+
updatedResults = APOLOGY_TEXT
|
567
|
+
|
568
|
+
if bot_available:
|
569
|
+
try:
|
570
|
+
otpValue = 0
|
571
|
+
alertUser = None
|
572
|
+
dbManager = DBManager()
|
573
|
+
otpValue, subsModel,subsValidity,alertUser = registerUser(user,forceFetch=True)
|
574
|
+
except Exception as e: # pragma: no cover
|
575
|
+
logger.error(e)
|
576
|
+
pass
|
577
|
+
userText = f"<b>UserID</b> : <code>{user.id}</code>"
|
578
|
+
try:
|
579
|
+
subscriptionModelNames = "\n<pre>Following basic and premium subscription models are available. Premium subscription allows for unlimited premium scans:\n"
|
580
|
+
for name,value in PKUserSusbscriptions().subscriptionKeyValuePairs.items():
|
581
|
+
if name == PKSubscriptionModel.No_Subscription.name:
|
582
|
+
subscriptionModelNames = f"{subscriptionModelNames}\n₹ {str(value).ljust(6)}: {name} (Only Basic Scans are free)\n"
|
583
|
+
else:
|
584
|
+
subscriptionModelNames = f"{subscriptionModelNames}\n₹ {str(value).ljust(6)}: {name}"
|
585
|
+
subscriptionModelNames = f"{subscriptionModelNames}</pre>\nPlease pay to subscribe:\n1. Using UPI(India) to <a href='https://tinyurl.com/v7h3t233'>PKScreener@APL</a> or\n2. Proudly <a href='https://github.com/sponsors/pkjmesra?frequency=recurring&sponsor=pkjmesra'><b>sponsor</b></a>\n\nPlease drop a message to @ItsOnlyPK on Telegram after paying to enable subscription manually or use \n\n/check UPI_UTR_HERE_After_Making_Payment to share transaction reference number to automatically enable subscription after making payment via UPI\n"
|
586
|
+
|
587
|
+
subscriptionModelName = PKUserSusbscriptions().subscriptionValueKeyPairs[subsModel]
|
588
|
+
if subscriptionModelName != PKSubscriptionModel.No_Subscription.name:
|
589
|
+
subscriptionModelName = f"{subscriptionModelName} (Expires on: {subsValidity})"
|
590
|
+
except Exception as e:
|
591
|
+
logger.error(e)
|
592
|
+
subscriptionModelName = PKSubscriptionModel.No_Subscription.name
|
593
|
+
pass
|
594
|
+
if sendOTP:
|
595
|
+
if otpValue == 0:
|
596
|
+
updatedResults = f"We are having difficulty generating OTP for your {userText}. Please try again later or reach out to @ItsOnlyPK."
|
597
|
+
else:
|
598
|
+
updatedResults = f"Please use the following to login to PKScreener:\n{userText}\n<b>OTP</b> : <code>{otpValue}</code>\n\nCurrent subscription : <b>{subscriptionModelName}</b>.\nCurrent alerts balance: <b>₹ {alertUser.balance if alertUser is not None else 0}</b>. {subscriptionModelNames}"
|
599
|
+
else:
|
600
|
+
updatedResults = f"Current subscription: <b>{subscriptionModelName}</b>.\nCurrent alerts balance: <b>₹ {alertUser.balance if alertUser is not None else 0}</b>. {subscriptionModelNames}"
|
601
|
+
if hasattr(updateCarrier, "reply_text"):
|
602
|
+
updateCarrier.reply_text(text=sanitiseTexts(updatedResults), reply_markup=default_markup(user=user),parse_mode="HTML")
|
603
|
+
elif hasattr(updateCarrier, "edit_message_text"):
|
604
|
+
editMessageText(query=updateCarrier,editedText=sanitiseTexts(updatedResults),reply_markup=default_markup(user=user))
|
605
|
+
shareUpdateWithChannel(update=update, context=context, optionChoices=f"/otp\n{updatedResults}")
|
591
606
|
return START_ROUTES
|
592
607
|
|
593
608
|
def subscribeToScannerAlerts(update: Update, context: CallbackContext) -> str:
|
@@ -622,11 +637,11 @@ def subscribeToScannerAlerts(update: Update, context: CallbackContext) -> str:
|
|
622
637
|
return START_ROUTES
|
623
638
|
dbManager = DBManager()
|
624
639
|
alertUser = dbManager.alertsForUser(int(user.id))
|
625
|
-
inlineMenus = []
|
626
640
|
query.answer()
|
627
641
|
menuText = ""
|
628
642
|
requiredBalance = 40 if str(scanId).upper().startswith("P") else 31
|
629
|
-
|
643
|
+
# upi://pay?pa=PKScreener@APL&pn=PKScreener&cu=INR
|
644
|
+
payWall = "Please pay to subscribe:\n1. Using UPI(India) to <a href='https://tinyurl.com/v7h3t233'>PKScreener@APL</a> or\n2. Proudly <a href='https://github.com/sponsors/pkjmesra?frequency=recurring&sponsor=pkjmesra'>sponsor</a>\n\nPlease drop a message to @ItsOnlyPK along with UTR and Scan details on Telegram after paying to enable subscription manually or use \n\n/check UPI_UTR_HERE_After_Making_Payment to share transaction reference number to automatically update your balance after making payment via UPI.\nAfter that you can try re-subscribing!"
|
630
645
|
if alertUser is not None and alertUser.balance >= 0:
|
631
646
|
# User has some balance
|
632
647
|
if len(alertUser.scannerJobs) > 0:
|
@@ -636,7 +651,7 @@ def subscribeToScannerAlerts(update: Update, context: CallbackContext) -> str:
|
|
636
651
|
else:
|
637
652
|
if alertUser.balance < requiredBalance:
|
638
653
|
# Insufficient balance
|
639
|
-
menuText = f"You need at least
|
654
|
+
menuText = f"You need at least <b>₹ {requiredBalance}</b> to subscribe to <b>{scanId} alerts for a day</b> ! Your current balance <b>₹ {alertUser.balance}</b> is <b>insufficient</b>. {payWall}"
|
640
655
|
else:
|
641
656
|
# Sufficient balance to subscribe to scanId
|
642
657
|
subscribed = dbManager.updateAlertSubscriptionModel(user.id,requiredBalance,scanId)
|
@@ -647,19 +662,10 @@ def subscribeToScannerAlerts(update: Update, context: CallbackContext) -> str:
|
|
647
662
|
|
648
663
|
elif alertUser is None or alertUser.balance == 0:
|
649
664
|
# Either user is not subscribed or has 0 balance
|
650
|
-
menuText = f"You need at least
|
665
|
+
menuText = f"You need at least <b>₹ {requiredBalance}</b> to subscribe to <b>{scanId} alerts for a day</b> ! Your current balance <b>₹ 0</b> is <b>insufficient</b>. {payWall}"
|
651
666
|
|
652
|
-
|
653
|
-
|
654
|
-
"Start", callback_data="start"
|
655
|
-
)
|
656
|
-
)
|
657
|
-
keyboard = [inlineMenus]
|
658
|
-
reply_markup = InlineKeyboardMarkup(keyboard)
|
659
|
-
if query.message.text == menuText:
|
660
|
-
menuText = f"{PKDateUtilities.currentDateTime()}:\n{menuText}"
|
661
|
-
menuText = f"{menuText}\n\nClick /start if you want to restart the session."
|
662
|
-
query.edit_message_text(text=menuText, reply_markup=reply_markup)
|
667
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session."
|
668
|
+
editMessageText(query=query,editedText=sanitiseTexts(menuText),reply_markup=default_markup(user=user))
|
663
669
|
return START_ROUTES
|
664
670
|
|
665
671
|
|
@@ -756,11 +762,9 @@ def XScanners(update: Update, context: CallbackContext) -> str:
|
|
756
762
|
)
|
757
763
|
keyboard = [inlineMenus]
|
758
764
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
759
|
-
if
|
760
|
-
|
761
|
-
|
762
|
-
query.edit_message_text(text=menuText, reply_markup=reply_markup)
|
763
|
-
DBManager().getOTP(user.id,user.username,f"{user.first_name} {user.last_name}",validityIntervalInSeconds=configManager.otpInterval)
|
765
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session."
|
766
|
+
editMessageText(query=query,editedText=sanitiseTexts(menuText),reply_markup=reply_markup)
|
767
|
+
registerUser(user)
|
764
768
|
return START_ROUTES
|
765
769
|
|
766
770
|
def getinlineMenuListRow(keyboardRows=[]):
|
@@ -817,7 +821,7 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
817
821
|
start(update, context)
|
818
822
|
return START_ROUTES
|
819
823
|
|
820
|
-
reply_markup = default_markup(
|
824
|
+
reply_markup = default_markup(user=user)
|
821
825
|
if (len(selection) == 2 and selection[0] in ["X","B"] and selection[1] in ["P1","P2","P3"]) or \
|
822
826
|
(len(selection) == 4 and selection[0] in ["P"] and selection[3] in ["P1","P2","P3"]): # Piped scan index options
|
823
827
|
nextOption = ""
|
@@ -862,10 +866,8 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
862
866
|
|
863
867
|
keyboard = keyboardRows
|
864
868
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
865
|
-
if
|
866
|
-
|
867
|
-
menuText = f"{menuText}\n\nClick /start if you want to restart the session."
|
868
|
-
query.edit_message_text(text=menuText, reply_markup=reply_markup)
|
869
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session."
|
870
|
+
editMessageText(query=query,editedText=sanitiseTexts(menuText),reply_markup=reply_markup)
|
869
871
|
return START_ROUTES
|
870
872
|
if len(selection) == 2 or (len(selection) == 3 and selection[2] == "P"):
|
871
873
|
if str(selection[1]).isnumeric():
|
@@ -986,7 +988,7 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
986
988
|
)
|
987
989
|
mns.append(menu().create("H", "Home", 2))
|
988
990
|
mns.append(menu().create("P", "More Options", 2))
|
989
|
-
elif str(selection[2]).isnumeric():
|
991
|
+
elif str(selection[2]).isnumeric() and selection[0].lower() not in ["p"]:
|
990
992
|
preSelection = f"{selection[0]}_{selection[1]}_{selection[2]}"
|
991
993
|
if selection[2] in SCANNER_MENUS_WITH_SUBMENU_SUPPORT:
|
992
994
|
menuText = m3.renderForMenu(
|
@@ -1001,7 +1003,7 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1001
1003
|
skip=["0","M","Z"],
|
1002
1004
|
)
|
1003
1005
|
menuText = f"{menuText}\n\nH > Home"
|
1004
|
-
menuText = f"{menuText}\
|
1006
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session."
|
1005
1007
|
mns.append(menu().create("H", "Home", 2))
|
1006
1008
|
else:
|
1007
1009
|
if selection[2] == "4": # Last N days
|
@@ -1030,7 +1032,7 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1030
1032
|
)
|
1031
1033
|
keyboard = keyboardRows
|
1032
1034
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
1033
|
-
|
1035
|
+
if (len(selection) >= 4 and selection[0].lower() not in ["p"]) or (len(selection) >= 3 and selection[0].lower() in ["p"]):
|
1034
1036
|
if len(selection) == 4:
|
1035
1037
|
if selection[2] in SCANNER_SUBMENUS_CHILDLEVEL_SUPPORT.keys() and selection[3] in SCANNER_SUBMENUS_CHILDLEVEL_SUPPORT[selection[2]]:
|
1036
1038
|
m0.renderForMenu(
|
@@ -1079,7 +1081,7 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1079
1081
|
)
|
1080
1082
|
menuText = f"{menuText}\n\nH > Home"
|
1081
1083
|
mns.append(menu().create("H", "Home", 3))
|
1082
|
-
menuText = f"{menuText}\
|
1084
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session."
|
1083
1085
|
if mns is not None:
|
1084
1086
|
for mnu in mns:
|
1085
1087
|
activeInlineRow = getinlineMenuListRow(keyboardRows)
|
@@ -1088,8 +1090,9 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1088
1090
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
1089
1091
|
if len(mns) == 0:
|
1090
1092
|
menuText = ''
|
1091
|
-
elif len(selection) > 4:
|
1092
|
-
if selection[0] in 'P' and len(selection[3]) == 0:
|
1093
|
+
elif len(selection) > 4 or (len(selection) >= 3 and selection[0].lower() in ["p"]):
|
1094
|
+
if (selection[0] in 'P' and ((len(selection) >= 4 and len(selection[3]) == 0) or (len(selection) == 3 and str(selection[2]).isnumeric()))):
|
1095
|
+
preSelection = query.data.upper().replace("C", "")
|
1093
1096
|
skipMenus = ["N"]
|
1094
1097
|
skipMenus.extend(INDEX_SKIP_MENUS_1_To_4)
|
1095
1098
|
# Create the menu text labels
|
@@ -1126,7 +1129,7 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1126
1129
|
)
|
1127
1130
|
keyboard = [inlineMenus]
|
1128
1131
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
1129
|
-
|
1132
|
+
elif len(mns) == 0:
|
1130
1133
|
menuText = ''
|
1131
1134
|
|
1132
1135
|
if menuText is None or len(menuText) == 0:
|
@@ -1135,9 +1138,9 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1135
1138
|
)
|
1136
1139
|
optionChoices = f"{optionChoices}{f' > {selection[4]}' if len(selection) > 4 else ''}".replace(" > >","").strip()
|
1137
1140
|
expectedTime = f"{'10 to 15' if '> 15' in optionChoices else '1 to 2'}"
|
1138
|
-
menuText = f"Thank you for choosing {optionChoices.replace(' > > ','')}. You will receive the notification/results in about {expectedTime} minutes. It generally takes 1-2 minutes for NSE (2000+) stocks and 10-15 minutes for NASDAQ (7300+).\n\nPKScreener had been free for a long time, but owing to cost/budgeting issues, only a basic set of features will always remain free for everyone. Consider donating to help cover the basic server costs or subscribe to premium, if not subscribed yet:\n\nUPI (India): PKScreener@APL \n\nor
|
1141
|
+
menuText = f"Thank you for choosing {optionChoices.replace(' > > ','')}. You will receive the notification/results in about {expectedTime} minutes. It generally takes 1-2 minutes for NSE (2000+) stocks and 10-15 minutes for NASDAQ (7300+).\n\nPKScreener had been free for a long time, but owing to cost/budgeting issues, only a basic set of features will always remain free for everyone. Consider donating to help cover the basic server costs or subscribe to premium, if not subscribed yet:\n\nUPI (India): <a href='https://tinyurl.com/v7h3t233'>PKScreener@APL</a> \n\nor <a href='https://github.com/sponsors/pkjmesra?frequency=recurring&sponsor=pkjmesra'>sponsor</a>"
|
1139
1142
|
|
1140
|
-
reply_markup = default_markup(
|
1143
|
+
reply_markup = default_markup(user=user)
|
1141
1144
|
options = ":".join(selection)
|
1142
1145
|
shouldSendUpdate = launchScreener(
|
1143
1146
|
options=options,
|
@@ -1147,7 +1150,7 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1147
1150
|
update=update,
|
1148
1151
|
)
|
1149
1152
|
if not shouldSendUpdate:
|
1150
|
-
|
1153
|
+
registerUser(user)
|
1151
1154
|
return START_ROUTES
|
1152
1155
|
try:
|
1153
1156
|
if optionChoices != "" and Channel_Id is not None and len(str(Channel_Id)) > 0:
|
@@ -1164,20 +1167,54 @@ def Level2(update: Update, context: CallbackContext) -> str:
|
|
1164
1167
|
sendUpdatedMenu(
|
1165
1168
|
menuText=menuText, update=update, context=context, reply_markup=reply_markup
|
1166
1169
|
)
|
1167
|
-
|
1170
|
+
scanRequest = optionChoices.replace(" ", "").replace(">", "_").replace(":","_").replace("_D","").upper()
|
1171
|
+
sendSubscriptionOption(update,context,scanRequest)
|
1172
|
+
registerUser(user)
|
1168
1173
|
return START_ROUTES
|
1169
1174
|
|
1170
|
-
def default_markup(
|
1171
|
-
mns = m0.renderForMenu(
|
1175
|
+
def default_markup(user=None,monitorIndex=0):
|
1176
|
+
mns = m0.renderForMenu(selectedMenu=None,
|
1177
|
+
skip=TOP_LEVEL_SCANNER_SKIP_MENUS[:len(TOP_LEVEL_SCANNER_SKIP_MENUS)-1],
|
1178
|
+
asList=True,
|
1179
|
+
renderStyle=MenuRenderStyle.STANDALONE,
|
1180
|
+
)
|
1181
|
+
if (PKDateUtilities.isTradingTime() and not PKDateUtilities.isTodayHoliday()[0]) or ("PKDevTools_Default_Log_Level" in os.environ.keys()) or sys.argv[0].endswith(".py"):
|
1182
|
+
mns.append(menu().create(f"MI_{monitorIndex}", "👩💻 🚀 Intraday Monitor", 2))
|
1183
|
+
if user is not None and user.username == OWNER_USER:
|
1184
|
+
mns.append(menu().create(f"DV_0", ("✅ Enable Logging" if not configManager.logsEnabled else "🚫 Disable Logging"), 2))
|
1185
|
+
mns.append(menu().create(f"DV_1", "🔄 Restart Bot", 2))
|
1186
|
+
keyboard = []
|
1187
|
+
inlineMenus = []
|
1188
|
+
lastRowMenus = []
|
1189
|
+
rowIndex = 0
|
1190
|
+
iconDict = {"X":"🕵️♂️ 🔍 ","B":"📈 🎯 ","P":"🧨 💥 ","MI":"","DV":"","VS":"🔔 📣 ","start":"🟢 🏁 "}
|
1172
1191
|
for mnu in mns:
|
1173
|
-
if mnu.menuKey in TOP_LEVEL_SCANNER_MENUS:
|
1192
|
+
if mnu.menuKey[0:2] in TOP_LEVEL_SCANNER_MENUS:
|
1193
|
+
rowIndex +=1
|
1174
1194
|
inlineMenus.append(
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
)
|
1195
|
+
InlineKeyboardButton(
|
1196
|
+
iconDict.get(str(mnu.menuKey[0:2])) + mnu.menuText.split("(")[0],
|
1197
|
+
callback_data="C" + str(mnu.menuKey),
|
1179
1198
|
)
|
1180
|
-
|
1199
|
+
)
|
1200
|
+
if rowIndex % 2 == 0:
|
1201
|
+
keyboard.append(inlineMenus)
|
1202
|
+
inlineMenus = []
|
1203
|
+
lastRowMenus.append(
|
1204
|
+
InlineKeyboardButton(
|
1205
|
+
iconDict.get("VS") + "Subscriptions",
|
1206
|
+
callback_data="VS_",
|
1207
|
+
)
|
1208
|
+
)
|
1209
|
+
lastRowMenus.append(
|
1210
|
+
InlineKeyboardButton(
|
1211
|
+
iconDict.get("start") + "Start",
|
1212
|
+
callback_data="start",
|
1213
|
+
)
|
1214
|
+
)
|
1215
|
+
if len(inlineMenus) > 0:
|
1216
|
+
keyboard.append(inlineMenus)
|
1217
|
+
keyboard.append(lastRowMenus)
|
1181
1218
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
1182
1219
|
return reply_markup
|
1183
1220
|
|
@@ -1185,14 +1222,8 @@ def default_markup(inlineMenus):
|
|
1185
1222
|
def sendUpdatedMenu(menuText, update: Update, context, reply_markup, replaceWhiteSpaces=True):
|
1186
1223
|
try:
|
1187
1224
|
menuText.replace(" ", "").replace(" ", "").replace("\t", "").replace(colorText.FAIL,"").replace(colorText.END,"").replace(colorText.WHITE,"") if replaceWhiteSpaces else menuText
|
1188
|
-
menuText = f"{menuText}\
|
1189
|
-
|
1190
|
-
menuText = f"{PKDateUtilities.currentDateTime()}:\n{menuText}"
|
1191
|
-
update.callback_query.edit_message_text(
|
1192
|
-
text=menuText,
|
1193
|
-
parse_mode="HTML",
|
1194
|
-
reply_markup=reply_markup,
|
1195
|
-
)
|
1225
|
+
menuText = f"{menuText}\nClick /start if you want to restart the session." if "/start" not in menuText else menuText
|
1226
|
+
editMessageText(query=update.callback_query,editedText=sanitiseTexts(menuText),reply_markup=reply_markup)
|
1196
1227
|
except Exception as e:# pragma: no cover
|
1197
1228
|
logger.log(e)
|
1198
1229
|
start(update, context)
|
@@ -1213,16 +1244,14 @@ def launchScreener(options, user, context, optionChoices, update):
|
|
1213
1244
|
isBasicScanRequest = True
|
1214
1245
|
break
|
1215
1246
|
if not isBasicScanRequest:
|
1216
|
-
responseText = f"Thank you for choosing {scanRequest}!\n\nThis
|
1247
|
+
responseText = f"Thank you for choosing {scanRequest}!\n\nThis {'Backtest' if str(scanRequest).startswith('B') else 'Scan'} request is, however, protected and is only available to premium subscribers. It seems like you are not subscribed to the paid/premium subscription to PKScreener.\nPlease checkout all premium options by sending out a request:\n\n/OTP\n\nFor basic/unpaid users, you can try out the following:\n/X_0 StockCode1,StockCode2,etc.\n/X_N\n/X_1\n"
|
1217
1248
|
if update is not None and update.message is not None:
|
1218
|
-
update.message.reply_text(sanitiseTexts(responseText))
|
1249
|
+
update.message.reply_text(sanitiseTexts(responseText),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1219
1250
|
else:
|
1220
|
-
responseText = f"{responseText}\
|
1221
|
-
|
1222
|
-
text=responseText,
|
1223
|
-
reply_markup=default_markup([]),
|
1224
|
-
)
|
1251
|
+
responseText = f"{responseText}\nClick /start if you want to restart the session."
|
1252
|
+
editMessageText(query=update.callback_query,editedText=sanitiseTexts(responseText),reply_markup=default_markup(user=user))
|
1225
1253
|
shareUpdateWithChannel(update=update, context=context, optionChoices=responseText)
|
1254
|
+
sendSubscriptionOption(update,context,scanRequest)
|
1226
1255
|
return False
|
1227
1256
|
|
1228
1257
|
if str(optionChoices.upper()).startswith("B"):
|
@@ -1236,13 +1265,10 @@ def launchScreener(options, user, context, optionChoices, update):
|
|
1236
1265
|
responseText = f"{responseText}\n\nStock-wise: https://pkjmesra.github.io/PKScreener/Backtest-Reports/PKScreener_{optionChoices}_backtest_result_StockSorted.html"
|
1237
1266
|
responseText = f"{responseText}\n\nOther Reports: https://pkjmesra.github.io/PKScreener/BacktestReports.html"
|
1238
1267
|
if update is not None and update.message is not None:
|
1239
|
-
update.message.reply_text(sanitiseTexts(responseText))
|
1268
|
+
update.message.reply_text(sanitiseTexts(responseText),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1240
1269
|
else:
|
1241
|
-
responseText = f"{responseText}\
|
1242
|
-
update.callback_query
|
1243
|
-
text=responseText,
|
1244
|
-
reply_markup=default_markup([]),
|
1245
|
-
)
|
1270
|
+
responseText = f"{responseText}\nClick /start if you want to restart the session."
|
1271
|
+
editMessageText(query=update.callback_query,editedText=sanitiseTexts(responseText),reply_markup=default_markup(user=user))
|
1246
1272
|
shareUpdateWithChannel(
|
1247
1273
|
update=update, context=context, optionChoices=optionChoices
|
1248
1274
|
)
|
@@ -1309,15 +1335,35 @@ def BBacktests(update: Update, context: CallbackContext) -> str:
|
|
1309
1335
|
]
|
1310
1336
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
1311
1337
|
responseText = "Backtesting NOT implemented yet in this Bot!\n\n\nYou can use backtesting by downloading the software from https://github.com/pkjmesra/PKScreener/"
|
1312
|
-
responseText = f"{responseText}\
|
1313
|
-
query
|
1314
|
-
|
1315
|
-
reply_markup=reply_markup,
|
1316
|
-
)
|
1317
|
-
DBManager().getOTP(user.id,user.username,f"{user.first_name} {user.last_name}",validityIntervalInSeconds=configManager.otpInterval)
|
1338
|
+
responseText = f"{responseText}\nClick /start if you want to restart the session."
|
1339
|
+
editMessageText(query=query,editedText=sanitiseTexts(responseText),reply_markup=default_markup(user=user))
|
1340
|
+
registerUser(user)
|
1318
1341
|
return START_ROUTES
|
1319
1342
|
|
1320
|
-
|
1343
|
+
def sendSubscriptionOption(update:Update,context:CallbackContext,scanId):
|
1344
|
+
updateCarrier = None
|
1345
|
+
if update is None:
|
1346
|
+
return
|
1347
|
+
else:
|
1348
|
+
if update.callback_query is not None:
|
1349
|
+
updateCarrier = update.callback_query
|
1350
|
+
if update.message is not None:
|
1351
|
+
updateCarrier = update.message
|
1352
|
+
if updateCarrier is None:
|
1353
|
+
return
|
1354
|
+
# Get user that sent /start and log his name
|
1355
|
+
user = updateCarrier.from_user
|
1356
|
+
reply_markup = {
|
1357
|
+
"inline_keyboard": [
|
1358
|
+
[{"text": f"Yes! Subscribe", "callback_data": f"SUB_{scanId}"}]
|
1359
|
+
],
|
1360
|
+
}
|
1361
|
+
message=f"Would you like to subscribe to this (<b>{scanId}</b>) automated scan alert for a day during market hours (NSE - IST timezone)? You will need to pay <b>₹ {'40' if str(scanId).upper().startswith('P') else '31'} (One time per day)</b> for automated alerts to only <b>{scanId}</b> all day on the day of subscription."
|
1362
|
+
if len(str(scanId).strip()) > 0 and not str(scanId).startswith("B"):
|
1363
|
+
context.bot.send_message(
|
1364
|
+
chat_id=user.id, text=message, reply_markup=reply_markup, parse_mode="HTML"
|
1365
|
+
)
|
1366
|
+
|
1321
1367
|
def end(update: Update, context: CallbackContext) -> str:
|
1322
1368
|
"""Returns `ConversationHandler.END`, which tells the
|
1323
1369
|
ConversationHandler that the conversation is over.
|
@@ -1325,10 +1371,8 @@ def end(update: Update, context: CallbackContext) -> str:
|
|
1325
1371
|
query = update.callback_query
|
1326
1372
|
query.answer()
|
1327
1373
|
responseText = "See https://github.com/pkjmesra/PKScreener/ for more details or join https://t.me/PKScreener. \n\n\nSee you next time!"
|
1328
|
-
responseText = f"{responseText}\
|
1329
|
-
query.
|
1330
|
-
text=responseText
|
1331
|
-
)
|
1374
|
+
responseText = f"{responseText}\nClick /start if you want to restart the session."
|
1375
|
+
editMessageText(query=query,editedText=sanitiseTexts(responseText),reply_markup=default_markup(query.from_user))
|
1332
1376
|
return ConversationHandler.END
|
1333
1377
|
|
1334
1378
|
|
@@ -1421,6 +1465,21 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1421
1465
|
if not bot_available:
|
1422
1466
|
start(update, context)
|
1423
1467
|
return START_ROUTES
|
1468
|
+
updateCarrier = None
|
1469
|
+
if update is None:
|
1470
|
+
return
|
1471
|
+
else:
|
1472
|
+
if hasattr(update, "callback_query") and update.callback_query is not None:
|
1473
|
+
updateCarrier = update.callback_query
|
1474
|
+
if hasattr(update, "message") and update.message is not None:
|
1475
|
+
updateCarrier = update.message
|
1476
|
+
if hasattr(update, "effective_message") and update.effective_message is not None:
|
1477
|
+
updateCarrier = update.effective_message
|
1478
|
+
if updateCarrier is None:
|
1479
|
+
return
|
1480
|
+
# Get user that sent /start and log his name
|
1481
|
+
user = updateCarrier.from_user
|
1482
|
+
|
1424
1483
|
msg = update.effective_message
|
1425
1484
|
try:
|
1426
1485
|
m = re.match(r"\s*/([0-9a-zA-Z_-]+)\s*(.*)", msg.text)
|
@@ -1451,7 +1510,7 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1451
1510
|
cmdText = f"{cmdText}\n/F_0 STOCK_CODE1,STOCK_CODE2 To find which all scanners had these stock codes(Reverse look up)"
|
1452
1511
|
|
1453
1512
|
if cmd.upper() in TOP_LEVEL_SCANNER_MENUS:
|
1454
|
-
shareUpdateWithChannel(update=update, context=context)
|
1513
|
+
shareUpdateWithChannel(update=update, context=context,optionChoices=msg)
|
1455
1514
|
m0.renderForMenu(
|
1456
1515
|
selectedMenu=None,
|
1457
1516
|
skip=TOP_LEVEL_SCANNER_SKIP_MENUS[:len(TOP_LEVEL_SCANNER_SKIP_MENUS)-1],
|
@@ -1474,8 +1533,8 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1474
1533
|
if cmd in ["x"]:
|
1475
1534
|
cmdText = f"{cmdText}\n\nFor option 0 <Screen stocks by the stock name>, please type in the command in the following format\n/X_0 SBIN\n or \n/X_0_0 SBIN\nand hit send where SBIN is the NSE stock code.For multiple stocks, you can type in \n/X_0 SBIN,ICICIBANK,OtherStocks\nYou can put in any number of stocks separated by space or comma(,)."
|
1476
1535
|
"""Send a message when the command /help is issued."""
|
1477
|
-
cmdText = f"{cmdText}\
|
1478
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1536
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1537
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1479
1538
|
return START_ROUTES
|
1480
1539
|
|
1481
1540
|
if update.message is None:
|
@@ -1483,7 +1542,7 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1483
1542
|
return START_ROUTES
|
1484
1543
|
|
1485
1544
|
if "x_0" in cmd or "x_0_0" in cmd or "b_0" in cmd or "g_0" in cmd or "f_0" in cmd:
|
1486
|
-
shareUpdateWithChannel(update=update, context=context)
|
1545
|
+
shareUpdateWithChannel(update=update, context=context,optionChoices=msg)
|
1487
1546
|
shouldScan = False
|
1488
1547
|
if len(args) > 0:
|
1489
1548
|
shouldScan = True
|
@@ -1504,17 +1563,19 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1504
1563
|
)
|
1505
1564
|
if result:
|
1506
1565
|
sendRequestSubmitted(cmd.upper(), update=update, context=context)
|
1566
|
+
scanRequest = cmd.upper().replace(" ", "").replace(">", "_").replace(":","_").replace("_D","").upper()
|
1567
|
+
sendSubscriptionOption(update,context,scanRequest)
|
1507
1568
|
return START_ROUTES
|
1508
1569
|
else:
|
1509
1570
|
if cmd in ["x"]:
|
1510
1571
|
cmdText = "For option 0 <Screen stocks by the stock name>, please type in the command in the following format\n/X_0 SBIN or /X_0_0 SBIN and hit send where SBIN is the NSE stock code.For multiple stocks, you can type in /X_0 SBIN,ICICIBANK,OtherStocks . You can put in any number of stocks separated by space or comma(,)."
|
1511
1572
|
"""Send a message when the command /help is issued."""
|
1512
|
-
cmdText = f"{cmdText}\
|
1513
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1573
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1574
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1514
1575
|
return START_ROUTES
|
1515
1576
|
|
1516
1577
|
if "p_" in cmd:
|
1517
|
-
shareUpdateWithChannel(update=update, context=context)
|
1578
|
+
shareUpdateWithChannel(update=update, context=context,optionChoices=msg)
|
1518
1579
|
selection = cmd.split("_")
|
1519
1580
|
if len(selection) == 2:
|
1520
1581
|
m0.renderForMenu(
|
@@ -1541,8 +1602,8 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1541
1602
|
cmdText = (
|
1542
1603
|
f"{cmdText}\n\n{cmd.commandTextKey()} for {cmd.commandTextLabel()}"
|
1543
1604
|
)
|
1544
|
-
cmdText = f"{cmdText}\
|
1545
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1605
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1606
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1546
1607
|
return START_ROUTES
|
1547
1608
|
elif len(selection) == 3:
|
1548
1609
|
m0.renderForMenu(
|
@@ -1556,8 +1617,8 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1556
1617
|
cmdText = (
|
1557
1618
|
f"{cmdText}\n\n/{cmd.upper()}{indexCmd.commandTextKey().replace('/X','')} for Piped scan of {indexCmd.commandTextLabel().replace('Scanners >',cmd.upper()+' >')}"
|
1558
1619
|
)
|
1559
|
-
cmdText = f"{cmdText}\
|
1560
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1620
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1621
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1561
1622
|
return START_ROUTES
|
1562
1623
|
elif len(selection) == 4:
|
1563
1624
|
options = ":".join(selection)
|
@@ -1570,10 +1631,12 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1570
1631
|
)
|
1571
1632
|
if result:
|
1572
1633
|
sendRequestSubmitted(cmd.upper(), update=update, context=context)
|
1634
|
+
scanRequest = cmd.upper().replace(" ", "").replace(">", "_").replace(":","_").replace("_D","").upper()
|
1635
|
+
sendSubscriptionOption(update,context,scanRequest)
|
1573
1636
|
return START_ROUTES
|
1574
1637
|
|
1575
1638
|
if "x_" in cmd or "b_" in cmd or "g_" in cmd:
|
1576
|
-
shareUpdateWithChannel(update=update, context=context)
|
1639
|
+
shareUpdateWithChannel(update=update, context=context,optionChoices=msg)
|
1577
1640
|
selection = cmd.split("_")
|
1578
1641
|
if len(selection) == 2:
|
1579
1642
|
m0.renderForMenu(
|
@@ -1605,14 +1668,16 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1605
1668
|
)
|
1606
1669
|
if result:
|
1607
1670
|
sendRequestSubmitted(cmd.upper(), update=update, context=context)
|
1671
|
+
scanRequest = cmd.upper().replace(" ", "").replace(">", "_").replace(":","_").replace("_D","").upper()
|
1672
|
+
sendSubscriptionOption(update,context,scanRequest)
|
1608
1673
|
return START_ROUTES
|
1609
1674
|
elif (
|
1610
1675
|
"x_" in cmd and selectedMenu.menuKey == "0"
|
1611
1676
|
): # a specific stock by name
|
1612
1677
|
cmdText = "For option 0 <Screen stocks by the stock name>, please type in the command in the following format\n/X_0 SBIN or /X_0_0 SBIN and hit send where SBIN is the NSE stock code.For multiple stocks, you can type in /X_0 SBIN,ICICIBANK,OtherStocks. You can put in any number of stocks separated by space or comma(,)."
|
1613
1678
|
"""Send a message when the command /help is issued."""
|
1614
|
-
cmdText = f"{cmdText}\
|
1615
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1679
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1680
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1616
1681
|
return START_ROUTES
|
1617
1682
|
cmds = m2.renderForMenu(
|
1618
1683
|
selectedMenu=selectedMenu,
|
@@ -1624,8 +1689,8 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1624
1689
|
cmdText = (
|
1625
1690
|
f"{cmdText}\n\n{cmd.commandTextKey()} for {cmd.commandTextLabel()}"
|
1626
1691
|
)
|
1627
|
-
cmdText = f"{cmdText}\
|
1628
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1692
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1693
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1629
1694
|
return START_ROUTES
|
1630
1695
|
elif len(selection) == 3:
|
1631
1696
|
m0.renderForMenu(
|
@@ -1662,8 +1727,8 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1662
1727
|
)
|
1663
1728
|
for cmd in cmds:
|
1664
1729
|
cmdText = f"{cmdText}\n\n{cmd.commandTextKey()} for {cmd.commandTextLabel()}"
|
1665
|
-
cmdText = f"{cmdText}\
|
1666
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1730
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1731
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1667
1732
|
return START_ROUTES
|
1668
1733
|
else:
|
1669
1734
|
if selection[2] == "4": # Last N days
|
@@ -1720,8 +1785,8 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1720
1785
|
)
|
1721
1786
|
for cmd in cmds:
|
1722
1787
|
cmdText = f"{cmdText}\n\n{cmd.commandTextKey()} for {cmd.commandTextLabel()}"
|
1723
|
-
cmdText = f"{cmdText}\
|
1724
|
-
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"))
|
1788
|
+
cmdText = f"{cmdText}\nClick /start if you want to restart the session."
|
1789
|
+
update.message.reply_text(sanitiseTexts(f"Choose an option:\n{cmdText}"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1725
1790
|
return START_ROUTES
|
1726
1791
|
|
1727
1792
|
options = ":".join(selection)
|
@@ -1734,31 +1799,39 @@ def command_handler(update: Update, context: CallbackContext) -> None:
|
|
1734
1799
|
)
|
1735
1800
|
if result:
|
1736
1801
|
sendRequestSubmitted(cmd.upper(), update=update, context=context)
|
1802
|
+
scanRequest = cmd.upper().replace(" ", "").replace(">", "_").replace(":","_").replace("_D","").upper()
|
1803
|
+
sendSubscriptionOption(update,context,scanRequest)
|
1737
1804
|
return START_ROUTES
|
1738
1805
|
if cmd == "y" or cmd == "h":
|
1739
|
-
shareUpdateWithChannel(update=update, context=context)
|
1806
|
+
shareUpdateWithChannel(update=update, context=context,optionChoices=msg)
|
1740
1807
|
from pkscreener.globals import showSendConfigInfo, showSendHelpInfo
|
1741
1808
|
if cmd == "y":
|
1742
1809
|
showSendConfigInfo(defaultAnswer='Y',user=str(update.message.from_user.id))
|
1743
1810
|
elif cmd == "h":
|
1744
1811
|
showSendHelpInfo(defaultAnswer='Y',user=str(update.message.from_user.id))
|
1745
|
-
# result = launchScreener(
|
1746
|
-
# options=f"{cmd.upper()}:",
|
1747
|
-
# user=update.message.from_user,
|
1748
|
-
# context=context,
|
1749
|
-
# optionChoices=cmd.upper(),
|
1750
|
-
# update=update,
|
1751
|
-
# )
|
1752
|
-
# sendRequestSubmitted(cmd.upper(), update=update, context=context)
|
1753
1812
|
return START_ROUTES
|
1754
|
-
update.message.reply_text(sanitiseTexts(f"{cmd.upper()} : Not implemented yet!"))
|
1813
|
+
update.message.reply_text(sanitiseTexts(f"{cmd.upper()} : Not implemented yet!"),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1755
1814
|
help_command(update=update, context=context)
|
1756
1815
|
|
1757
1816
|
|
1758
1817
|
def sendRequestSubmitted(optionChoices, update, context):
|
1759
|
-
|
1760
|
-
update
|
1761
|
-
|
1818
|
+
updateCarrier = None
|
1819
|
+
if update is None:
|
1820
|
+
return
|
1821
|
+
else:
|
1822
|
+
if hasattr(update, "callback_query") and update.callback_query is not None:
|
1823
|
+
updateCarrier = update.callback_query
|
1824
|
+
if hasattr(update, "message") and update.message is not None:
|
1825
|
+
updateCarrier = update.message
|
1826
|
+
if hasattr(update, "effective_message") and update.effective_message is not None:
|
1827
|
+
updateCarrier = update.effective_message
|
1828
|
+
if updateCarrier is None:
|
1829
|
+
return
|
1830
|
+
# Get user that sent /start and log his name
|
1831
|
+
user = updateCarrier.from_user
|
1832
|
+
menuText = f"Thank you for choosing {optionChoices}. You will receive the notification/results in about 1-2 minutes! \n\nConsider donating to help keep this project going:\nUPI: <a href='https://tinyurl.com/v7h3t233'>PKScreener@APL</a> \nor <a href='https://github.com/sponsors/pkjmesra?frequency=recurring&sponsor=pkjmesra'>sponsor</a>"
|
1833
|
+
update.message.reply_text(sanitiseTexts(menuText),reply_markup=default_markup(user=user),parse_mode="HTML")
|
1834
|
+
# help_command(update=update, context=context)
|
1762
1835
|
shareUpdateWithChannel(
|
1763
1836
|
update=update, context=context, optionChoices=optionChoices
|
1764
1837
|
)
|
@@ -1799,15 +1872,16 @@ def help_command(update: Update, context: CallbackContext) -> None:
|
|
1799
1872
|
asList=True,
|
1800
1873
|
renderStyle=MenuRenderStyle.STANDALONE,
|
1801
1874
|
)
|
1802
|
-
cmdText = "
|
1875
|
+
cmdText = "/otp to generate an OTP to login to PKScreener desktop console\n/check UPI_UTR_HERE_After_Making_Payment to share transaction reference number to automatically enable subscription after making payment via UPI"
|
1803
1876
|
for cmd in cmds:
|
1804
|
-
|
1805
|
-
|
1877
|
+
if cmd.menuKey not in TOP_LEVEL_MARKUP_SKIP_MENUS:
|
1878
|
+
cmdText = f"{cmdText}\n{cmd.commandTextKey()} : {cmd.commandTextLabel()}"
|
1806
1879
|
|
1807
1880
|
"""Send a message when the command /help is issued."""
|
1808
1881
|
if update is not None and update.message is not None:
|
1809
1882
|
update.message.reply_text(
|
1810
|
-
sanitiseTexts(f"You can begin by typing in /start (Recommended) and hit send!\
|
1883
|
+
sanitiseTexts(f"You can begin by typing in /start (Recommended) and hit send!\nOR\nChoose an option:\n{cmdText}\n\nWe recommend you start by clicking on this /start"),
|
1884
|
+
reply_markup=default_markup(user=user),parse_mode="HTML"
|
1811
1885
|
) # \n\nThis bot restarts every hour starting at 5:30am IST until 10:30pm IST to keep it running on free servers. If it does not respond, please try again in a minutes to avoid the restart duration!
|
1812
1886
|
query = update.message
|
1813
1887
|
message = f"Name: <b>{query.from_user.first_name}</b>, Username:@{query.from_user.username} with ID: <b>@{str(query.from_user.id)}</b> began using the bot!"
|
@@ -1815,8 +1889,7 @@ def help_command(update: Update, context: CallbackContext) -> None:
|
|
1815
1889
|
context.bot.send_message(
|
1816
1890
|
chat_id=int(f"-{Channel_Id}"), text=message, parse_mode="HTML"
|
1817
1891
|
)
|
1818
|
-
|
1819
|
-
|
1892
|
+
registerUser(user)
|
1820
1893
|
|
1821
1894
|
def _shouldAvoidResponse(update):
|
1822
1895
|
sentFrom = []
|
@@ -2010,6 +2083,7 @@ def runpkscreenerbot(availability=True) -> None:
|
|
2010
2083
|
CallbackQueryHandler(Level2, pattern="^" + str("CB_")),
|
2011
2084
|
CallbackQueryHandler(Level2, pattern="^" + str("CP_")),
|
2012
2085
|
CallbackQueryHandler(subscribeToScannerAlerts, pattern="^" + str("SUB_")),
|
2086
|
+
CallbackQueryHandler(viewSubscriptionOptions, pattern="^" + str("VS_")),
|
2013
2087
|
# CallbackQueryHandler(Level2, pattern="^" + str("CG_")),
|
2014
2088
|
CallbackQueryHandler(end, pattern="^" + str("CZ") + "$"),
|
2015
2089
|
CallbackQueryHandler(start, pattern="^"),
|
@@ -2038,6 +2112,7 @@ def runpkscreenerbot(availability=True) -> None:
|
|
2038
2112
|
if bot_available:
|
2039
2113
|
# Run the intraday monitor
|
2040
2114
|
initializeIntradayTimer()
|
2115
|
+
loadRegisteredUsers()
|
2041
2116
|
# Run the bot until the user presses Ctrl-C
|
2042
2117
|
# application.run_polling(allowed_updates=Update.ALL_TYPES)
|
2043
2118
|
# Start the Bot
|