from flask import Flask, request, jsonify, render_template from config import Config from db import PostScheduler, UsersMedods, VkAPI, VkPost, db, MedodsAPI, ApiEndpoint from medods_handler import updateMedodsUsers from scheduler import enable_publish_job, get_scheduler_status, start_scheduler from http_client import send_request import logging import os from vk_handler import handle_vk_post app = Flask(__name__) app.config.from_object(Config) db.init_app(app) os.makedirs("logs", exist_ok=True) logging.basicConfig( level=logging.INFO, format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", handlers=[ logging.FileHandler(Config.LOG_FILE, encoding="utf-8"), logging.StreamHandler(), ], ) logger = logging.getLogger(__name__) @app.before_request def init(): db.create_all() start_scheduler() enable_publish_job() logger.info("Приложение запущено") @app.route("/") def index(): return render_template("index.html") @app.route("/medods", methods=["GET"]) def medods(): medods_api = MedodsAPI.query.first() data = {} if medods_api: apiKey = False if medods_api.identity and medods_api.secretKey: apiKey = True data = { "url": medods_api.url, "apiKey": apiKey, } return render_template("medods.html", data=data) @app.route("/vk", methods=["GET"]) def vk(): vkDB = VkAPI.query.first() data = {} if vkDB: data = {"vk_settings": vkDB.toDict()} return render_template("vk.html", data=data) @app.route("/posts", methods=["GET"]) def posts(): medodsUsers = UsersMedods.query.all() if len(medodsUsers) > 0: medodsUsers = [user.toDict() for user in medodsUsers] vkPost = VkPost.query.first() if vkPost: vkPost = vkPost.toDict() schedulerStatus = get_scheduler_status() schedulerSettings = PostScheduler.query.first() if schedulerSettings: schedulerSettings = schedulerSettings.toDict() return render_template( "posts.html", data={ "medodsUsers": medodsUsers, "vkPost": vkPost, "schedulerStatus": schedulerStatus, "schedulerSettings": schedulerSettings, }, ) @app.route("/api/medods", methods=["POST"]) def api_medods(): try: data = request.json apiKey = data.get("apiKey", None) url = data.get("url", None) if url is not None: logger.info("Получен url") try: medodsRecord = MedodsAPI.query.first() medodsRecord.url = url db.session.commit() logger.info("Обновлен url") except Exception: db.session.merge(MedodsAPI(url=url)) db.session.commit() logger.info("Добавлен url") if apiKey: logger.info("Получены ключи") try: medodsRecord = MedodsAPI.query.first() medodsRecord.identity = apiKey["identity"] medodsRecord.secretKey = apiKey["secretKey"] db.session.commit() logger.info("Обновлены ключи") except Exception: db.session.merge( MedodsAPI( identity=apiKey["identity"], secretKey=apiKey["secretKey"] ) ) db.session.commit() logger.info("Добавлены ключи") return jsonify({"ok": True}) except Exception as e: logger.error(f"Ошибка при обновлении ключей: {e}") return jsonify({"ok": False}), 500 @app.route("/api/requests", methods=["GET", "POST", "PATCH", "DELETE"]) def api_requests(): requestData = ( request.json if request.method in ["POST", "PATCH", "DELETE"] else None ) match request.method: case "DELETE": try: db.session.execute( db.delete(ApiEndpoint).where(ApiEndpoint.id == requestData["id"]) ) db.session.commit() except Exception as e: logger.error(f"Ошибка при удалении запроса {requestData['id']}: {e}") logger.info("Удален запрос") return jsonify({"status": "ok"}) case "POST": logger.info("Добавлен/обновлен запрос") if "id" in requestData: logger.info("Обновлен запрос") try: db.session.execute( db.update(ApiEndpoint) .where(ApiEndpoint.id == requestData["id"]) .values( method=requestData.get("method"), title=requestData.get("title"), url_path=requestData.get("url_path"), payload=requestData.get("payload", {}), query_params=requestData.get("query_params", {}), ) ) db.session.commit() except Exception as e: logger.error(f"Ошибка при обновлении запроса: {e}") return jsonify({"status": "ok"}) else: logger.info("Добавлен запрос") try: db.session.merge(ApiEndpoint(**requestData)) db.session.commit() except Exception as e: logger.error(f"Ошибка при добавлении запроса: {e}") return jsonify({"status": "ok"}) case "PATCH": logger.info("Выполнен запрос") try: requestParams = ApiEndpoint.query.filter_by( id=requestData["id"] ).first() medodsDB = MedodsAPI.query.first() baseUrl = medodsDB.url response = send_request( requestParams.method, f"{baseUrl}{requestParams.url_path}", requestParams.payload, requestParams.query_params, ) exitData = {} try: exitData = response.json() except: exitData = response.text return jsonify(exitData) except Exception as e: logger.error(f"Ошибка при выполнении запроса: {e}") return jsonify({"status": "error"}), 500 case "GET": logger.info("Получен список запросов") requestsDB = ApiEndpoint.query.all() requestsList = [r.toDict() for r in requestsDB] return jsonify( { "status": "ok", "requests": requestsList, } ) case _: logger.error("Неверный метод запроса") return jsonify({"status": "error"}), 405 @app.route("/api/vk", methods=["POST"]) def api_vk(): requestData = request.json if "id" in requestData: logger.info("Обновлен запрос") try: db.session.execute( db.update(VkAPI) .where(VkAPI.id == requestData["id"]) .values( group_id=( int(requestData.get("group_id", 0)) if requestData.get("group_id") else 0 ), access_token=requestData.get("access_token"), base_photo_url=( int(requestData.get("base_photo_url", 0)) if requestData.get("base_photo_url") else 0 ), ) ) db.session.commit() except Exception as e: logger.error(f"Ошибка при обновлении запроса: {e}") return jsonify({"status": "ok"}) else: logger.info("Добавлен запрос") try: db.session.merge(VkAPI(**requestData)) db.session.commit() except Exception as e: logger.error(f"Ошибка при добавлении запроса: {e}") return jsonify({"status": "ok"}) @app.route("/api/posts", methods=["POST", "GET"]) def api_posts(): match request.method: case "POST": requestData = request.json logger.info("Настройки публикации и расписания") vkPostData = requestData.get("vkPostData", None) if vkPostData: selectedUsers = vkPostData.get("selectedUsers", None) static_text = vkPostData.get("static_text", None) full_name = vkPostData.get("full_name", None) logger.info("Обновление настроек публикации") try: vkPost = VkPost.query.first() if vkPost: if selectedUsers: vkPost.selected_users = selectedUsers if static_text: vkPost.static_text = static_text if full_name is not None: vkPost.full_name = full_name else: vkPostData["selected_users"] = vkPostData.pop("selectedUsers") db.session.merge(VkPost(**vkPostData)) db.session.commit() except Exception as e: logger.error(f"Ошибка при обновлении настроек публикации: {e}") schedulerData = requestData.get("schedulerData", None) if schedulerData: logger.info("Обновление расписания публикации") try: scheduler = PostScheduler.query.first() startTime = schedulerData.get("startTime", None) endTime = schedulerData.get("endTime", None) interval_minutes = schedulerData.get("interval_minutes", None) enabled = schedulerData.get("enabled", None) if scheduler: if startTime: scheduler.start_hour = int(startTime) if endTime: scheduler.end_hour = int(endTime) if interval_minutes: scheduler.interval_minutes = int(interval_minutes) if enabled is not None: scheduler.enabled = enabled else: db.session.merge( PostScheduler( start_hour=int(startTime), end_hour=int(endTime), interval_minutes=int(interval_minutes), enabled=enabled, ) ) db.session.commit() except Exception as e: logger.error(f"Ошибка при обновлении расписания публикации: {e}") return jsonify({"status": "ok"}) case "GET": queryParams = request.args.to_dict() action = queryParams.get("action", None) if action: match action: case "update_users": logger.info("Обновить список пользователей") result = updateMedodsUsers() return jsonify({"ok": result}) case "handle_posts": logger.info("Выполнить публикацию") handle_vk_post() return jsonify({"ok": True}) case _: logger.error("Неверный метод запроса") return jsonify({"status": "error"}), 405 return jsonify({"ok": False, "status": "error", "message": "no action"}) case _: logger.error("Неверный метод запроса") return jsonify({"status": "error"}), 405 def with_app_context(func): def wrapper(*args, **kwargs): from app import app with app.app_context(): return func(*args, **kwargs) return wrapper if __name__ == "__main__": # app.run(debug=True) app.run(debug=True, host="0.0.0.0", port=80)