ChaterJee 0.1.9__py3-none-any.whl → 0.2.0__py3-none-any.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.
ChaterJee/ChaterJee.py CHANGED
@@ -7,8 +7,8 @@ import pickle
7
7
  import html
8
8
  import traceback
9
9
  import logging, json
10
- from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo, ReplyKeyboardMarkup, KeyboardButton
11
- from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, ConversationHandler, filters, PollAnswerHandler, PollHandler
10
+ from telegram import Update, InlineKeyboardMarkup, InlineKeyboardButton, WebAppInfo, ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove
11
+ from telegram.ext import Updater, ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, ConversationHandler, filters, PollAnswerHandler, PollHandler
12
12
  from telegram.constants import ParseMode
13
13
  import os.path
14
14
  import threading
@@ -19,11 +19,14 @@ start_txt = \
19
19
  """
20
20
  I am ChaterJee, a Research assistant Bot developed by Pallab Dutta in 2025.
21
21
 
22
- ChaterJee helps you to:
23
- - Receive research updates
24
- - Start new computational experiments
22
+ *TEXT*
23
+ acts as a bash command and runs on host terminal.
25
24
 
26
- even when you are at a remote location.
25
+ *COMMANDS*
26
+ /start : returns this text.
27
+ /jobs : shows your jobs
28
+ /clear : clears chat history
29
+ /edit file.json : let you edit the file.json
27
30
 
28
31
  """
29
32
 
@@ -40,8 +43,10 @@ class ChatLogs:
40
43
  self.jobs = {}
41
44
 
42
45
  def cmdTRIGGER(self, read_timeout=7, get_updates_read_timeout=42):
46
+ #que = asyncio.Queue()
43
47
  application = ApplicationBuilder().token(self.TOKEN).read_timeout(read_timeout)\
44
48
  .get_updates_read_timeout(get_updates_read_timeout).build()
49
+ #updater = Updater(application.bot, update_queue=que)
45
50
 
46
51
  start_handler = CommandHandler('start', self.start)
47
52
  application.add_handler(start_handler)
@@ -49,195 +54,56 @@ class ChatLogs:
49
54
  fEdit_handler = CommandHandler('edit', self.EditorBabu)
50
55
  application.add_handler(fEdit_handler)
51
56
 
52
- cmd_handler = CommandHandler('sh', self.commands)
53
- application.add_handler(cmd_handler)
57
+ #cmd_handler = CommandHandler('sh', self.commands)
58
+ #application.add_handler(cmd_handler)
54
59
 
55
- #jobs_handler = CommandHandler('jobs', self.ShowJobs)
56
- #application.add_handler(jobs_handler)
60
+ cancel_handler = CommandHandler('cancel', self.cancel)
61
+ application.add_handler(cancel_handler)
57
62
 
58
63
  jobs_handler = ConversationHandler(\
59
- entry_points=[CommandHandler("jobs", self.ShowJobs)],\
64
+ entry_points=[CommandHandler("jobs", self.ShowJobs), CommandHandler("clear", self.ask2clear)],\
60
65
  states={
61
- 0: [MessageHandler(filters.Regex(f"^({'|'.join(list(self.jobs.keys()))})$"), self.StatJobs)],
66
+ 0: [MessageHandler(filters.Regex("^(JOB)"), self.StatJobs)],
67
+ 1: [MessageHandler(filters.Regex("^(Yes|No)$"), self.ClearChat)],
62
68
  },
63
69
  fallbacks=[CommandHandler("cancel", self.cancel)],
64
70
  )
65
-
66
71
  application.add_handler(jobs_handler)
67
- #add_handler = CommandHandler('add', addDICT)
68
- #application.add_handler(add_handler)
69
- #run_handler = CommandHandler('run', runCMD)
70
- #application.add_handler(run_handler)
71
- #com_handler = CommandHandler('com', comCMD)
72
- #application.add_handler(com_handler)
73
- #exit_handler = CommandHandler('exit', exitCMD)
74
- #application.add_handler(exit_handle)
75
- #clear_handler = CommandHandler('clear', clsCMD)
76
- #application.add_handler(clear_handler)
77
- #jedit_handler = CommandHandler('edit', editJSON) # JSON file editor
78
- #application.add_handler(jedit_handler)
79
72
 
80
73
  application.add_handler(MessageHandler(filters.StatusUpdate.WEB_APP_DATA, self.web_app_data))
81
- #application.add_handler(MessageHandler(filters.TEXT, self.commands))
74
+ application.add_handler(MessageHandler(filters.TEXT & ~(filters.COMMAND | filters.Regex("^(JOB:|Yes$|No$)")), self.commands))
82
75
 
83
- application.run_polling()
76
+ #await application.shutdown()
77
+ #await application.initialize()
84
78
 
85
- def strSMS(self, update, context):
86
- self.smsID.append(update.message.message_id)
87
- self.txt=update.message.text
88
- cmd = self.txt.split(' ')[0]
89
- args = self.txt.split(' ')[1:]
90
- if cmd == '/add':
91
- self.addDICT(args)
92
- elif cmd == '/run':
93
- self.cmdRUN(args)
94
- elif cmd == '/com':
95
- self.cmdCOM(args)
96
- elif cmd == '/exit':
97
- self.EXIT()
98
- elif cmd == '/clear':
99
- self.cls()
100
- elif cmd[0] == '/':
101
- self.txt = 'command not found !'
102
- self.sendUPDATE()
103
- else:
104
- self.txt = "Sorry I can only read '/commands', not 'texts'."
105
- self.sendUPDATE()
79
+ #updater = Updater(application.bot, update_queue=que)
80
+ #await updater.initialize()
81
+ #await updater.start_polling()
82
+ application.run_polling()
106
83
 
107
- def addDICT(self, context):
108
- try:
109
- key = context[0]
110
- eql = context[1]
111
- if ('$' in key) and (eql == '='):
112
- val = context[2]
113
- self.dict[key]=val
114
- self.txt = 'added to dictionary'
115
- elif ('$' in key) and (eql == '-1'):
116
- del self.dict[key]
117
- self.txt = 'removed from dictionary'
118
- else:
119
- self.txt = 'pass the command as:\n/add $key = val'
120
- except:
121
- self.txt = 'pass the command as:\n/add $key = val'
122
- self.sendUPDATE()
123
-
124
- def fmtDICT(self, context):
125
- key = []
126
- idx = []
127
- c = context
128
- for i in range(len(context)):
129
- w = context[i]
130
- if '$' in w:
131
- key.append(w)
132
- idx.append(i)
133
- for j in range(len(idx)):
134
- val = self.dict[key[j]]
135
- c[idx[j]] = val
136
- return c
137
-
138
- #async def cmdRUN(update: object, context: ContextTypes.DEFAULT_TYPE) -> None:
139
- def cmdRUN(self, context):
140
- context = self.fmtDICT(context)
141
- cmd0 = context[0]
142
- if cmd0=='cd':
143
- cmd1 = context[1]
144
- try:
145
- os.chdir(cmd1)
146
- self.txt=os.popen('pwd').read()
147
- except:
148
- self.txt='path not found'
149
- else:
150
- cmd=' '.join(context)
151
- try:
152
- self.txt=os.popen('%s'%(cmd)).read()
153
- except:
154
- self.txt='error !'
155
- self.sendUPDATE()
156
-
157
- def readout(self):
158
- time.sleep(1)
159
- fout=open('stdout.txt','r')
160
- ferr=open('stderr.txt','r')
161
- lout = fout.readlines()
162
- out = ' '.join(lout)
163
- lerr = ferr.readlines()
164
- err = ' '.join(lerr)
165
- #out = out.strip()
166
- #err = err.strip()
167
- if out == '' and err == '':
168
- self.txt = 'command executed !'
169
- elif out != '' and err == '':
170
- self.txt = 'out:\n%s\n'%(out)
171
- elif out == '' and err != '':
172
- self.txt = 'err:\n%s\n'%(err)
173
- else:
174
- self.txt = 'out:\n%s\nerr:\n%s\n'%(out,err)
175
- print(self.txt)
176
- fout.close()
177
- ferr.close()
178
- tout=open('stdout.txt','w')
179
- tout.close()
180
- terr=open('stderr.txt','w')
181
- terr.close()
182
-
183
- def cmdCOM(self, context):
184
- context = self.fmtDICT(context)
185
- if context[0]!='i' and context[0]!='kill':
186
- self.fout = open('stdout.txt','w')
187
- self.ferr = open('stderr.txt','w')
188
- self.p=Popen(context,stdin=PIPE,stdout=self.fout,stderr=self.ferr,universal_newlines=True,bufsize=0)
189
- self.fout.close()
190
- self.ferr.close()
191
- elif context[0]=='kill':
192
- self.txt = 'process terminated'
193
- self.p.terminate()
194
- else:
195
- comsg = ' '.join(context[1:])
196
- self.p.stdin.write(comsg+'\n')
197
- self.readout()
198
-
199
- #out,err = self.p.communicate()
200
- #out = ' '.join(self.p.stdout)
201
- #err = ' '.join(self.p.stderr)
202
- #self.txt = "out: \n%s\n\nerr: \n%s"%(out,err)
203
- self.sendUPDATE()
204
-
205
- def EXIT(self):
206
- os.chdir(self.path)
207
- self.txt = "Thanks! I am signing off."
208
- self.sendUPDATE()
209
- time.sleep(2)
210
- self.cls()
211
- threading.Thread(target=self.shutdown).start()
212
-
213
- def shutdown(self):
214
- self.updater.stop()
215
- self.updater.is_idle = False
216
-
217
- def cls(self):
218
- for i in self.smsID:
219
- self.BOT.delete_message(chat_id=self.CHATID, message_id=i)
220
- self.smsID = []
221
-
222
- def sendUPDATE(self):
223
- self.BOT.sendChatAction(chat_id=self.CHATID, action="typing")
224
- msg = self.BOT.sendMessage(chat_id=self.CHATID, text=self.txt)
225
- self.smsID.append(msg.message_id)
84
+ async def sendUpdate(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
85
+ if len(self.txt):
86
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
87
+ msg = await context.bot.send_message(chat_id=self.CHATID, text=self.txt, parse_mode='Markdown')
88
+ self.smsID.append(msg.message_id)
226
89
 
227
90
  async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
228
- msg = await context.bot.send_message(chat_id=self.CHATID, text=start_txt)
229
- self.smsID.append(msg.message_id)
91
+ self.smsID.append(update.message.message_id)
92
+ self.txt = start_txt
93
+ await self.sendUpdate(update, context)
230
94
 
231
95
  def register_to_log(self, job_name: str, log_path: str):
232
96
  self.jobs[job_name] = log_path
233
97
 
234
- async def ShowJobs(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
98
+ async def ShowJobs(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
99
+ self.smsID.append(update.message.message_id)
235
100
  jobs_file = self.home / ".data" / "JOB_status.json"
236
101
  with open(jobs_file, 'r') as ffr:
237
102
  jobs = json.load(ffr)
238
103
  self.jobs = jobs
239
104
 
240
105
  reply_keyboard = [[f'{job}'] for job in list(self.jobs.keys())]
106
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
241
107
  msg = await update.message.reply_text("Select a job to get updates on",\
242
108
  reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True, input_field_placeholder="Select the job."\
243
109
  ),\
@@ -246,7 +112,7 @@ class ChatLogs:
246
112
  return 0
247
113
 
248
114
  async def StatJobs(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
249
- print("I'm inside StatJobs")
115
+ self.smsID.append(update.message.message_id)
250
116
  job_name = update.message.text
251
117
 
252
118
  jobs_file = self.home / ".data" / "JOB_status.json"
@@ -258,15 +124,23 @@ class ChatLogs:
258
124
  logFILE = jobs[job_name]['logFILE']
259
125
  logIMAGE = jobs[job_name]['logIMAGE']
260
126
 
261
- txt = self.get_last_line(logDIR / logFILE)
262
- print(txt)
127
+ self.txt = self.get_last_line(logDIR / logFILE)
263
128
 
264
- if txt is not None:
265
- msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
266
- self.smsID.append(msg.message_id)
129
+ if self.txt is None:
130
+ self.txt = 'No updates found'
131
+ #await self.sendUpdate(update, context)
132
+ #msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
133
+ #self.smsID.append(msg.message_id)
134
+
135
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
136
+ msg = await update.message.reply_text(
137
+ self.txt, reply_markup=ReplyKeyboardRemove()
138
+ )
139
+ self.smsID.append(msg.message_id)
267
140
 
268
141
  try:
269
142
  with open(logDIR / logIMAGE, 'rb') as ffrb:
143
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
270
144
  msg = await context.bot.send_photo(chat_id=self.CHATID, photo=ffrb)
271
145
  self.smsID.append(msg.message_id)
272
146
  except:
@@ -295,10 +169,16 @@ class ChatLogs:
295
169
  return last_line.strip()
296
170
 
297
171
  async def cancel(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
298
- pass
172
+ self.smsID.append(update.message.message_id)
173
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
174
+ msg = await update.message.reply_text(
175
+ "Keyboard is refreshed!", reply_markup=ReplyKeyboardRemove()
176
+ )
177
+ self.smsID.append(msg.message_id)
178
+ return ConversationHandler.END
299
179
 
300
180
  async def EditorBabu(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
301
- print('Opening Json file in edit mode')
181
+ self.smsID.append(update.message.message_id)
302
182
  if len(context.args) == 1:
303
183
  file_path = context.args[0]
304
184
  if os.path.exists(file_path):
@@ -307,6 +187,7 @@ class ChatLogs:
307
187
  encoded_params = urllib.parse.quote(json.dumps(JsonStr))
308
188
  file_name = file_path.split('/')[-1]
309
189
  extender = f"?variables={encoded_params}&fileNAME={file_name}"
190
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
310
191
  msg = await update.message.reply_text(
311
192
  "Editor-Babu is opening the Json file.",
312
193
  reply_markup=ReplyKeyboardMarkup.from_button(
@@ -317,13 +198,14 @@ class ChatLogs:
317
198
  ),
318
199
  )
319
200
  else:
320
- txt = f"File {file_path} not Found!"
321
- msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
201
+ self.txt = f"File {file_path} not Found!"
202
+ #msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
322
203
  else:
323
- txt = "Expected a JSON file as argument. Nothing provided."
324
- msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
204
+ self.txt = "Expected a JSON file as argument. Nothing provided."
205
+ #msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
325
206
 
326
- self.smsID.append(msg.message_id)
207
+ #self.smsID.append(msg.message_id)
208
+ await self.sendUpdate(update, context)
327
209
 
328
210
  async def web_app_data(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None :
329
211
  data = json.loads(update.effective_message.web_app_data.data)
@@ -338,39 +220,66 @@ class ChatLogs:
338
220
  JSdata = {**JSdata, **data}
339
221
  with open(fileNAME, 'w') as ffw:
340
222
  json.dump(JSdata, ffw, indent=4)
341
- txt = f"edits are saved to {fileNAME}"
223
+ self.txt = f"edits are saved to {fileNAME}"
342
224
  else:
343
- txt = f"No new changes! file kept unchanged."
225
+ self.txt = f"No new changes! file kept unchanged."
344
226
 
345
- msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
346
- self.smsID.append(msg.message_id)
227
+ #msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
228
+ #self.smsID.append(msg.message_id)
229
+ await self.sendUpdate(update, context)
347
230
 
348
231
  async def commands(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
349
232
  self.smsID.append(update.message.message_id)
350
- cmd2run = ' '.join(context.args) #update.message.text.strip()
233
+ #cmd2run = ' '.join(context.args) #update.message.text.strip()
234
+ cmd2run = update.message.text.strip()
351
235
  cmd0 = cmd2run.split(' ')[0]
352
- if cmd0=='cd':
236
+ if cmd0[0]=='/':
237
+ print('It came here')
238
+ pass
239
+ elif cmd0=='cd':
353
240
  cmd1 = cmd2run[3:]
354
241
  try:
355
242
  os.chdir(cmd1)
356
- txt=os.popen('pwd').read()
243
+ self.txt=os.popen('pwd').read()
357
244
  except:
358
- txt='path not found'
245
+ self.txt='path not found'
359
246
  elif cmd0=='clear':
360
- for i in self.smsID:
361
- await context.bot.delete_message(chat_id=self.CHATID, message_id=i)
362
- self.smsID = []
363
- txt=''
247
+ self.txt="This clears the terminal screen!\nTo clear telegram screen type /clear"
364
248
  else:
365
249
  print('command: ',cmd2run)
366
250
  cmd=cmd2run
367
251
  try:
368
- txt=os.popen('%s'%(cmd)).read()
252
+ self.txt=os.popen('%s'%(cmd)).read()
369
253
  except:
370
- txt='error !'
371
- if len(txt):
372
- msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
373
- self.smsID.append(msg.message_id)
254
+ self.txt='error !'
255
+ await self.sendUpdate(update, context)
256
+ #msg = await context.bot.send_message(chat_id=self.CHATID, text=txt)
257
+ #self.smsID.append(msg.message_id)
258
+
259
+ async def ClearChat(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
260
+ self.smsID.append(update.message.message_id)
261
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
262
+ msg = await update.message.reply_text(
263
+ "Full chat history will be cleared", reply_markup=ReplyKeyboardRemove()
264
+ )
265
+ self.smsID.append(msg.message_id)
266
+ for i in self.smsID:
267
+ await context.bot.delete_message(chat_id=self.CHATID, message_id=i)
268
+
269
+ self.smsID = []
270
+ return ConversationHandler.END
271
+
272
+ async def ask2clear(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
273
+ self.smsID.append(update.message.message_id)
274
+ reply_keyboard = [['Yes','No']]
275
+ print(reply_keyboard)
276
+ await context.bot.sendChatAction(chat_id=self.CHATID, action="typing")
277
+ msg = await update.message.reply_text("Entire chat history in the current session will be cleared. Proceed?",\
278
+ reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True, input_field_placeholder="Select to proceed."\
279
+ ),\
280
+ )
281
+ self.smsID.append(msg.message_id)
282
+ return 1
374
283
 
375
284
 
376
285
  class NoteLogs:
@@ -397,7 +306,7 @@ class NoteLogs:
397
306
 
398
307
  logDIR = str(_logDIR)
399
308
 
400
- self.jobNAME = jobNAME
309
+ self.jobNAME = f"JOB: {jobNAME}"
401
310
  self.logDIR = logDIR
402
311
  self.logFILE = logFILE
403
312
  self.logIMAGE = logIMAGE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ChaterJee
3
- Version: 0.1.9
3
+ Version: 0.2.0
4
4
  Summary: Communicate your project updates via Telegram Bot!
5
5
  Author: Pallab Dutta
6
6
  Author-email: pallab9997@gmail.com
@@ -0,0 +1,6 @@
1
+ ChaterJee/ChaterJee.py,sha256=92ao2kjhi2aG7whJ8G9M2NqH9OTfMH_FzVoxHz1BD1Q,12744
2
+ ChaterJee/__init__.py,sha256=tZmkZY2XbzJ8rHDh8nOmb1W73kPecPv3xcEiCPwkZf4,98
3
+ chaterjee-0.2.0.dist-info/METADATA,sha256=dCbblGHGsdVmsKU8LluqL_7mwwQmMPGwg1rVOcMkti0,340
4
+ chaterjee-0.2.0.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
5
+ chaterjee-0.2.0.dist-info/top_level.txt,sha256=Z1UAYoaNybpDiKjqa1yFpti_q0FNECVItb3-9yAh3gM,10
6
+ chaterjee-0.2.0.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- ChaterJee/ChaterJee.py,sha256=I9T9XNy5nW6UqVau8P9Wo05yxVVwvQ56tNE4QzCygns,14601
2
- ChaterJee/__init__.py,sha256=tZmkZY2XbzJ8rHDh8nOmb1W73kPecPv3xcEiCPwkZf4,98
3
- chaterjee-0.1.9.dist-info/METADATA,sha256=aD8ZvWKDItN5MspAowfqxx_ZsV69lM749IQqiDoNiak,340
4
- chaterjee-0.1.9.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
5
- chaterjee-0.1.9.dist-info/top_level.txt,sha256=Z1UAYoaNybpDiKjqa1yFpti_q0FNECVItb3-9yAh3gM,10
6
- chaterjee-0.1.9.dist-info/RECORD,,