[O] Reimplement scheduler so that only one thread is created
This commit is contained in:
+62
-46
@@ -1,91 +1,107 @@
|
|||||||
import difflib
|
import difflib
|
||||||
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from telegram.ext import Job, CallbackContext, Updater
|
from telegram.ext import CallbackContext, Updater
|
||||||
|
|
||||||
from src.database import Database
|
from src.database import Database
|
||||||
from src.utils import wrap, render, sendRequest
|
from src.utils import wrap, render, sendRequest
|
||||||
|
|
||||||
|
|
||||||
class Scheduler:
|
class CacheEntry:
|
||||||
tasks: {str: {str: Job}} = {}
|
user: str
|
||||||
cache: {str: {str: str}} = {}
|
name: str
|
||||||
|
time: float
|
||||||
|
text: str
|
||||||
|
|
||||||
|
def __init__(self, user: str, name: str, time: float, text: str):
|
||||||
|
self.user = user
|
||||||
|
self.name = name
|
||||||
|
self.time = time
|
||||||
|
self.text = text
|
||||||
|
|
||||||
|
|
||||||
|
class Scheduler:
|
||||||
|
# storage[user][name] = CacheEntry
|
||||||
|
storage: {str: {str: CacheEntry}} = {}
|
||||||
|
|
||||||
|
# Constructor
|
||||||
def __init__(self, database: Database, updater: Updater):
|
def __init__(self, database: Database, updater: Updater):
|
||||||
self.database = database
|
self.database = database
|
||||||
self.updater = updater
|
self.updater = updater
|
||||||
|
|
||||||
def create(self, user: str, taskName: str, request):
|
# Start job
|
||||||
if user not in self.cache:
|
self.job = self.updater.job_queue.run_repeating(self.update, interval=5, first=0)
|
||||||
self.cache[user] = {}
|
|
||||||
|
|
||||||
def task(context: CallbackContext):
|
# Update tasks
|
||||||
# Send request
|
def update(self, context: CallbackContext):
|
||||||
text = wrap(sendRequest(request))
|
now = time.time()
|
||||||
|
nowText = datetime.now().strftime('%b %d %Y %H-%M-%S')
|
||||||
|
|
||||||
|
# Function to update a single task
|
||||||
|
def updateTask(cache: CacheEntry):
|
||||||
|
request = self.database.reqs[cache.user][cache.name]
|
||||||
|
if now - cache.time < request.get('interval', 120):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Execute request
|
||||||
|
text: str = wrap(sendRequest(request))
|
||||||
|
|
||||||
# First time http request
|
# First time http request
|
||||||
if taskName not in self.cache[user]:
|
if cache.text == '':
|
||||||
self.cache[user][taskName] = text
|
cache.text = text
|
||||||
|
|
||||||
# Compare diff
|
# Generate diff
|
||||||
else:
|
diffRaw = difflib.unified_diff(cache.text.splitlines(True), text.splitlines(True), fromfile='before', tofile='after')
|
||||||
# Generate diff
|
diff = ''.join(diffRaw)
|
||||||
diffRaw = difflib.unified_diff(self.cache[user][taskName].splitlines(1), text.splitlines(1),
|
|
||||||
fromfile='before', tofile='after')
|
|
||||||
diff = ''.join(diffRaw)
|
|
||||||
self.cache[user][taskName] = text
|
|
||||||
|
|
||||||
if diff != '':
|
# Update cache
|
||||||
# Render diff
|
cache.text = text
|
||||||
doc = BytesIO(render(diff))
|
|
||||||
time = datetime.now().strftime('%b %d %Y %H-%M-%S')
|
|
||||||
fileName = 'diff %s %s.png' % (taskName, time)
|
|
||||||
caption = '*%s Changed!*' % taskName
|
|
||||||
|
|
||||||
# Send as file
|
if diff != '':
|
||||||
context.bot.send_document(int(user), doc, fileName, caption, parse_mode='markdown')
|
# Render diff
|
||||||
|
doc = BytesIO(render(diff))
|
||||||
|
fileName = 'diff %s %s.png' % (cache.name, nowText)
|
||||||
|
caption = '*%s Changed!*' % cache.name
|
||||||
|
|
||||||
return task
|
# Send as file
|
||||||
|
context.bot.send_document(int(user), doc, fileName, caption, parse_mode='markdown')
|
||||||
|
|
||||||
|
# Update all tasks
|
||||||
|
for user in self.storage:
|
||||||
|
for name in self.storage[user]:
|
||||||
|
updateTask(self.storage[user][name])
|
||||||
|
|
||||||
|
# Start a task
|
||||||
def start(self, user: str, name: str):
|
def start(self, user: str, name: str):
|
||||||
if self.isStarted(user, name):
|
if self.isStarted(user, name):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
request = self.database.reqs[user][name]
|
request = self.database.reqs[user][name]
|
||||||
if user not in self.tasks:
|
if user not in self.storage:
|
||||||
self.tasks[user] = {}
|
self.storage[user] = {}
|
||||||
|
|
||||||
self.tasks[user][name] = self.updater.job_queue.run_repeating(self.create(user, name, request), interval=request.get('interval', 120), first=0)
|
# Add task
|
||||||
|
self.storage[user][name] = CacheEntry(user, name, 0, '')
|
||||||
# Keep record
|
|
||||||
if not request['enabled']:
|
if not request['enabled']:
|
||||||
request['enabled'] = True
|
request['enabled'] = True
|
||||||
self.database.save()
|
self.database.save()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# Stop a task
|
||||||
def stop(self, user: str, name: str):
|
def stop(self, user: str, name: str):
|
||||||
if not self.isStarted(user, name):
|
if not self.isStarted(user, name):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Stop and remove task
|
# Stop and remove task
|
||||||
job = self.tasks[user][name]
|
self.storage[user].pop(name, None)
|
||||||
job.enabled = False
|
|
||||||
job.schedule_removal()
|
|
||||||
self.tasks[user].pop(name, None)
|
|
||||||
self.database.reqs[user][name]['enabled'] = False
|
self.database.reqs[user][name]['enabled'] = False
|
||||||
self.database.save()
|
self.database.save()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# Check if a task is started
|
||||||
def isStarted(self, user: str, name: str):
|
def isStarted(self, user: str, name: str):
|
||||||
return user in self.tasks and name in self.tasks[user]
|
return user in self.storage and name in self.storage[user]
|
||||||
|
|
||||||
def updateInterval(self, user: str, name: str):
|
|
||||||
if not self.isStarted(user, name):
|
|
||||||
return False
|
|
||||||
|
|
||||||
self.stop(user, name)
|
|
||||||
self.start(user, name)
|
|
||||||
return True
|
|
||||||
|
|||||||
Reference in New Issue
Block a user