first commit

This commit is contained in:
Tema 2023-03-03 23:40:08 +02:00
commit 01f19ebb1d
Signed by: tema
GPG Key ID: 21FDB6D162488F6F
8 changed files with 317 additions and 0 deletions

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Bot files
*.ini
!example_config.ini
*.json
!configs/timetable/groups.json
*.jpg
*.db
*.sqlite3
*.txt
*.pem
!requirements.txt
test.py
venv/
.vscode/

33
bot.py Normal file
View File

@ -0,0 +1,33 @@
import logging
import time
import logging
import sched
import threading
from load import config, viber, app
import handlers
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
def set_webhook(viber):
viber.unset_webhook()
viber.set_webhook(config.webhook.webhook_url)
if __name__ == '__main__':
scheduler = sched.scheduler(time.time, time.sleep)
scheduler.enter(5, 1, set_webhook, (viber,))
t = threading.Thread(target=scheduler.run)
t.start()
context = (config.cert["cert"], config.cert["key"])
app.run(host=config.webhook.host,
port=int(config.webhook.port),
debug=True,
ssl_context=context
)

32
config.py Normal file
View File

@ -0,0 +1,32 @@
from configparser import ConfigParser
from easydict import EasyDict as edict
CONFIG_FILE = 'config.ini'
data = ConfigParser()
data.read(CONFIG_FILE)
config = edict()
config["cert"] = edict()
for section in data.sections():
config[section] = edict()
for key, value in data.items(section):
config[section][key] = value
config["cert"] = {
"cert": f"{config.webhook.cert_folder}/{config.webhook.cert}",
"key": f"{config.webhook.cert_folder}/{config.webhook.key}"
}
config["data_file"] = f"{config.parser.folder}/{config.parser.file}"
def parse_bool(section=None, key=None, text=None):
if text is not None:
return text.lower() in ['yes', 'true']
if section is not None and key is not None:
return config[section][key].lower() in ['yes', 'true']

109
handlers.py Normal file
View File

@ -0,0 +1,109 @@
import io
import base64
from flask import request, Response, send_file
from viberbot.api.messages.url_message import URLMessage
from viberbot.api.messages.text_message import TextMessage
from viberbot.api.messages.picture_message import PictureMessage
from viberbot.api.messages.keyboard_message import KeyboardMessage
from viberbot.api.viber_requests import ViberMessageRequest
from viberbot.api.viber_requests import ViberConversationStartedRequest
from load import app, logger, viber, config
from config import parse_bool
from parser.parser import get_about_replacements, docs_parse
ENABLE_PARSER = parse_bool(text=config.parser.enable_parse)
KEYBOARD = {
"Type": "keyboard",
"Buttons": [
{
"Columns": 6,
"Rows": 1,
"BgColor": "#e6f5ff",
"BgLoop": True,
"ActionType": "reply",
"ActionBody": "replaces",
#"ReplyType": "message",
"Text": "Заміни"
},
{
"Columns": 3,
"Rows": 2,
"BgColor": "#e6f5ff",
"BgLoop": True,
"ActionType": "reply",
"ActionBody": "link",
#"ReplyType": "message",
"Text": "Посилання на файл"
}
]
}
if ENABLE_PARSER:
KEYBOARD["Buttons"].append({
"Columns": 3,
"Rows": 2,
"BgColor": "#e6f5ff",
"BgLoop": True,
"ActionType": "reply",
"ActionBody": "update",
#"ReplyType": "message",
"Text": "Обновити дані"
})
else:
KEYBOARD["Buttons"][1]["Columns"] = 6
def get_text_button(index: int):
return KEYBOARD["Buttons"][index]["ActionBody"]
@app.route('/', methods=['POST'])
def incoming():
logger.debug("received request. post data: {0}".format(request.get_data()))
viber_request = viber.parse_request(request.get_data().decode('utf8'))
if isinstance(viber_request, ViberConversationStartedRequest):
viber.send_messages(viber_request.user.id, [
KeyboardMessage(keyboard=KEYBOARD)
])
if isinstance(viber_request, ViberMessageRequest):
message = viber_request.message.text
if message == "id": viber.send_messages(viber_request.sender.id, [TextMessage(text=viber_request.sender.id, keyboard=KEYBOARD)])
if message == get_text_button(0):
data = get_about_replacements()
if 'image' in data:
viber.send_messages(viber_request.sender.id, [
PictureMessage(
media=f"{config.webhook.webhook_url}/image",
keyboard=KEYBOARD
)
])
elif message == get_text_button(1):
viber.send_messages(viber_request.sender.id, [
URLMessage(media=config.parser.link, keyboard=KEYBOARD)
])
elif ENABLE_PARSER and message == get_text_button(2) and viber_request.sender.id:
if viber_request.sender.id not in config.parser.admins.split(","):
viber.send_messages(viber_request.sender.id, [TextMessage(text="Ви не адміністратор!")])
else:
try:
docs_parse()
viber.send_messages(viber_request.sender.id, [
TextMessage(text="Замены обновлены!", keyboard=KEYBOARD)])
except Exception as e:
print(e)
viber.send_messages(viber_request.sender.id, [
TextMessage(text='Ошибка обновления', keyboard=KEYBOARD)])
return Response(status=200)
@app.route('/image')
def get_image():
data = get_about_replacements()
if 'image' in data:
return send_file(io.BytesIO(base64.b64decode(data['data']['all'])), mimetype='image/jpeg')

18
load.py Normal file
View File

@ -0,0 +1,18 @@
import logging
from flask import Flask
from viberbot import Api
from viberbot.api.bot_configuration import BotConfiguration
from config import config
logger = logging.getLogger(__name__)
app = Flask(__name__)
viber = Api(BotConfiguration(
name=config.bot.name,
avatar=config.bot.avatar,
auth_token=config.bot.token,
))

2
parser/__init__.py Normal file
View File

@ -0,0 +1,2 @@
from .parser import get_about_replacements, docs_parse
__all__ = ['get_about_replacements', 'docs_parse']

67
parser/parser.py Normal file
View File

@ -0,0 +1,67 @@
import base64
import json
import datetime
from datetime import datetime as dt
import requests
from bs4 import BeautifulSoup
try:
from load import config
except ImportError: config = None
try:
from .utils import *
except ImportError:
from utils import *
headers = {
'user-agent':(
"Mozilla/5.0 (Windows NT 10.0; WOW64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/62.0.3202.9 Safari/537.36"
)
}
def date_parser_helper(days:int, parse:str="%d.%m.20%y"):
return dt.strftime(
dt.now() +
datetime.timedelta(days=days),
parse
)
def docs_parse():
output = {
"data":{},
"another_teacher":None
}
page = requests.get(config.parser.link, headers=headers)
page.encoding = 'utf-8'
soup = BeautifulSoup(page.text, "lxml")
# Это в идеале нужно переписать...
url = image_parser(soup)
with requests.get(url=url, allow_redirects=True, stream=True) as r:
output['image'] = True
output['date'] = 'невозможно получить!'
output['data']['all'] = base64.b64encode(r.content).decode('utf-8')
with open(config.data_file, 'w') as f:
json.dump(output, f, ensure_ascii=False)
f.close()
def get_about_replacements() -> dict:
with open(config.data_file, 'r') as f:
data = json.loads(f.read())
f.close()
return data
if __name__ == "__main__":
docs_parse()

34
parser/utils.py Normal file
View File

@ -0,0 +1,34 @@
from bs4 import BeautifulSoup
from typing import Any
def table_parser(soup: BeautifulSoup, output):
#Date parser
date = (soup.find("main").findAll('span', style="color:black"))[1]
output["date"] = date.text.replace(u'\xa0', u'')
#Replaces parser
replaces = soup.findAll('tr')
for data in replaces:
text = (
data.find("td", valign="top")
.find("span", style="color:black")
.text.replace(u'\xa0', u'')
)
group = (
data.find("span", style="color:black")
.text.replace(" ", "").replace(u'\xa0', u''))
output["data"][group] = text
return output
def image_parser(soup: BeautifulSoup):
image: Any
extension = ('png', 'jpg')
main = soup.find("main")
for ext in extension:
image = main.select(f'img[src$=".{ext}"]')
if image:
return image[0]['src']