taslim19 commited on
Commit
d384b52
·
0 Parent(s):
Dockerfile ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use Python 3.11 slim image
2
+ FROM python:3.11-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install system dependencies
8
+ RUN apt-get update && apt-get install -y \
9
+ git \
10
+ curl \
11
+ wget \
12
+ && rm -rf /var/lib/apt/lists/*
13
+
14
+ # Copy requirements first for better caching
15
+ COPY requirements.txt .
16
+
17
+ # Install Python dependencies
18
+ RUN pip install --no-cache-dir -r requirements.txt
19
+
20
+ # Copy the entire application
21
+ COPY . .
22
+
23
+ # Create necessary directories
24
+ RUN mkdir -p /app/logs
25
+
26
+ # Expose port
27
+ EXPOSE 8080
28
+
29
+ # Set environment variables
30
+ ENV PYTHONPATH=/app
31
+ ENV PORT=8080
32
+
33
+ # Health check
34
+ HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
35
+ CMD curl -f http://localhost:8080/ || exit 1
36
+
37
+ # Run the application
38
+ CMD ["python", "-m", "OneApi"]
OneApi/__init__.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from motor.motor_asyncio import AsyncIOMotorClient
2
+ from pymongo import MongoClient
3
+ import logging
4
+ from variables import *
5
+ import os
6
+ from quart import Quart
7
+ from pyrogram import *
8
+ from variables import *
9
+ import asyncio
10
+
11
+ logging.basicConfig(
12
+ format="[OneApi] %(name)s - %(levelname)s - %(message)s",
13
+ handlers=[logging.FileHandler("log.txt"), logging.StreamHandler()],
14
+ level=logging.INFO,
15
+ )
16
+
17
+ MONGO_DB_URI = os.environ.get("MONGO_DB_URL") or VAR_MONGO_DB_URI
18
+ API_ID = os.environ.get("API_ID") or VAR_API_ID
19
+ API_HASH = os.environ.get("API_HASH") or VAR_API_HASH
20
+ HANDLER = ["/"]
21
+ TOKEN = os.environ.get("TOKEN") or VAR_TOKEN
22
+ MY_VERSION = 0.1
23
+ DEVS = os.environ.get("DEVS") or VAR_DEVS
24
+ # _______________________________________
25
+ if not API_ID or not API_HASH or not TOKEN or not MONGO_DB_URI:
26
+ raise ValueError("Bro thought he can run anything lol, i mean you forgot some vars put on variables.py")
27
+ exit()
28
+ # _-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_-_+_|
29
+ if len(TOKEN) > 50: bot = Client("OneApi", session_string=TOKEN, api_id=API_ID, api_hash=API_HASH, plugins=dict(root="OneApi/pyro"))
30
+ else: bot = Client("OneApi", bot_token=TOKEN, api_id=API_ID, api_hash=API_HASH, plugins=dict(root="OneApi/pyro"))
31
+ # ———— R U N ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
32
+ async def run(command):
33
+ try:
34
+ process = await asyncio.create_subprocess_shell(
35
+ command,
36
+ stdout=asyncio.subprocess.PIPE,
37
+ stderr=asyncio.subprocess.PIPE,
38
+ start_new_session=True
39
+ )
40
+ stdout, stderr = await process.communicate()
41
+ if stdout:
42
+ return stdout.decode().strip()
43
+ if stderr:
44
+ return stderr.decode().strip()
45
+ except Exception as e:
46
+ logging.error(f"Failed to run command '{command}': {e}")
47
+ return False
48
+ # _______________________________________________________________
49
+ DATABASE = AsyncIOMotorClient(MONGO_DB_URI)["OneApi"]
50
+ app = Quart(__name__)
OneApi/__main__.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from quart_cors import cors
2
+ from quart import *
3
+ import asyncio
4
+ import os
5
+ from . import *
6
+
7
+ # BLUEPRINTS _____________________
8
+ from .api.exists import exists_bp
9
+ from .api.create_user import create_user_bp
10
+ from .api.get_projects import get_projects_bp
11
+ from .api.create_project import create_project_bp
12
+ from .api.delete_project import delete_project_bp
13
+ from .api.user_info import user_info_bp
14
+ from .api.get_repos import get_repos_bp
15
+ from .api.delete_user import delete_user_bp
16
+ from .api.disconnect_git import disconnect_git_bp
17
+ from .api.set_repo import set_repo_bp
18
+ from .api.project_info import project_info_bp
19
+ from .api.host import host_bp
20
+
21
+ app.register_blueprint(exists_bp)
22
+ app.register_blueprint(create_user_bp)
23
+ app.register_blueprint(get_projects_bp)
24
+ app.register_blueprint(create_project_bp)
25
+ app.register_blueprint(delete_project_bp)
26
+ app.register_blueprint(user_info_bp)
27
+ app.register_blueprint(get_repos_bp)
28
+ app.register_blueprint(delete_user_bp)
29
+ app.register_blueprint(disconnect_git_bp)
30
+ app.register_blueprint(set_repo_bp)
31
+ app.register_blueprint(project_info_bp)
32
+ app.register_blueprint(host_bp)
33
+ # ---------------------------------
34
+
35
+ app = cors(app, allow_origin="*")
36
+
37
+ @app.route('/')
38
+ async def home():
39
+ return jsonify({'success': 'server online'}), 200
40
+
41
+ if __name__ == '__main__':
42
+ app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
OneApi/api/create_project.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ create_project_bp = Blueprint('create_project', __name__)
7
+
8
+ @app.route('/create_project/', methods=['POST'])
9
+ async def create_project():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data and not 'name' in data and not 'plan' in data:
12
+ return jsonify({'error': 'missing user_id or name'}), 400
13
+ user_id = int(data.get('user_id'))
14
+ name = data.get('name')
15
+ plan = data.get('plan')
16
+ mano = await user.create_project(name, user_id, plan)
17
+ if mano == 'ok':
18
+ return jsonify({'message': 'Successfully created'}), 200
19
+ elif 'Error' in mano:
20
+ return jsonify({'error': mano}), 400
21
+ else:
22
+ return jsonify({'message': mano}), 400
OneApi/api/create_user.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ create_user_bp = Blueprint('create_user', __name__)
7
+
8
+ @app.route('/create_user/', methods=['POST'])
9
+ async def create_user():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data and not 'name' in data: return jsonify({'error': 'missing user_id & name'}), 400
12
+ user_id = int(data.get('user_id'))
13
+ name = data.get('name')
14
+ d = await user.create(name, user_id)
15
+ if d == 'exists':
16
+ return jsonify({'message': "user exists"}), 400
17
+ elif 'Error' in str(d):
18
+ return jsonify({'error': d}), 400
19
+ elif d =='ok':
20
+ return jsonify({'message': 'done'}), 200
21
+ elif d == "Not connected":
22
+ return jsonify({'message': 'The user is not connected with GitHub app.'}), 400
OneApi/api/delete_project.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ delete_project_bp = Blueprint('delete_project', __name__)
7
+
8
+ @app.route('/delete_project/', methods=['POST'])
9
+ async def delete_project():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data and not 'project_id' in data:
12
+ return jsonify({'error': 'missing user_id or project_id'}), 400
13
+ user_id = int(data.get('user_id'))
14
+ project_id = int(data.get('project_id'))
15
+ mano = await user.delete_project(user_id, project_id)
16
+ if mano == 'Project not found' or mano == 'not exists':
17
+ return jsonify({'message': mano}), 404
18
+ elif 'Error' in mano:
19
+ return jsonify({'error': mano}), 400
20
+ elif 'ok' in mano:
21
+ return jsonify({'message': mano}), 200
OneApi/api/delete_user.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ delete_user_bp = Blueprint('delete_user', __name__)
7
+
8
+ @app.route('/delete_user/', methods=['POST'])
9
+ async def delete_user():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data: return jsonify({'error': 'missing user_id'}), 400
12
+ user_id = int(data.get('user_id'))
13
+ d = await user.delete_user(user_id)
14
+ if d is True:
15
+ return jsonify({"message": "Successfully deleted user!"}), 200
16
+ elif "Error" in d:
17
+ return jsonify({"error": d}), 400
OneApi/api/disconnect_git.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+ import logging
5
+
6
+ user = user()
7
+ disconnect_git_bp = Blueprint('disconnect_git', __name__)
8
+
9
+ @app.route('/disconnect_git/', methods=['POST'])
10
+ async def disconnect_git():
11
+ data = await request.get_json()
12
+ if not data or not 'user_id' in data: return jsonify({'error': 'missing user_id'}), 400
13
+ user_id = int(data.get('user_id'))
14
+ mano = await user.disconnect_git(user_id)
15
+ if mano is True:
16
+ return jsonify({"message": "Successfully disconnected git"}), 200
17
+ elif 'Error' in mano:
18
+ return jsonify({'error': mano}), 400
OneApi/api/exists.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+ import logging
5
+
6
+ user = user()
7
+ exists_bp = Blueprint('exists', __name__)
8
+
9
+ @app.route('/exists/', methods=['POST'])
10
+ async def exists():
11
+ data = await request.get_json()
12
+ if not data or not 'user_id' in data: return jsonify({'error': 'missing user_id'}), 400
13
+ user_id = int(data.get('user_id'))
14
+
15
+ d = await user.find(user_id, check=True)
16
+ if d: return jsonify({'message': 'user exists'}), 200
17
+ elif not d: return jsonify({'message': "user not found"}), 404
18
+ elif 'Error' in d: return jsonify({'error': d}), 400
19
+ else: logging.info(d)
OneApi/api/get_projects.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ get_projects_bp = Blueprint('get_projects', __name__)
7
+
8
+ @app.route('/get_projects/', methods=['POST'])
9
+ async def get_projects():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data: return jsonify({'error': 'missing user_id'}), 400
12
+ user_id = int(data.get('user_id'))
13
+ ohk = await user.get_projects(user_id)
14
+ if ohk == "projects not found" or ohk == "not exists":
15
+ return jsonify({"message": ohk}), 404
16
+ elif 'Error' in ohk:
17
+ return jsonify({"error": ohk}), 400
18
+ return jsonify({"message": ohk}), 200
OneApi/api/get_repos.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ get_repos_bp = Blueprint('get_repos', __name__)
7
+
8
+ @app.route('/get_repos/', methods=['POST'])
9
+ async def get_repos():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data: return jsonify({'error': 'missing user_id'}), 400
12
+ user_id = int(data.get('user_id'))
13
+ d = await user.get_repos(user_id)
14
+ if d == "not exists":
15
+ return jsonify({'message': 'user not exists'}), 404
16
+ elif d == 'failed':
17
+ return jsonify({'message': "Failed to get user repos"}), 400
18
+ elif 'Error' in d:
19
+ return jsonify({'error': d}), 400
20
+ else:
21
+ return jsonify({'message': d}), 200
OneApi/api/host.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ import logging
4
+ from .. import *
5
+ from ..deployment.deployment import Deployment
6
+
7
+ user = user()
8
+ deploy = Deployment()
9
+ host_bp = Blueprint('host', __name__)
10
+
11
+ @app.route('/host/', methods=['POST'])
12
+ async def host():
13
+ data = await request.get_json()
14
+ if not data or not 'user_id' in data and not 'project_id' in data: return jsonify({'error': 'missing user_id or project_id'}), 400
15
+ user_id = int(data.get('user_id'))
16
+ project_id = int(data.get('project_id'))
17
+
18
+ mm = await deploy.host(user_id, project_id)
19
+ logging.info(f"DEBUG HOST API 18: {mm}")
20
+ if mm is True:
21
+ return jsonify({'message': 'Successfully hosted!'}), 200
22
+ return jsonify({'message': mm}), 400
OneApi/api/project_info.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ project_info_bp = Blueprint('project_info', __name__)
7
+
8
+ @app.route('/project_info/', methods=['POST'])
9
+ async def project_info():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data and not 'project_id' in data: return jsonify({'error': 'missing user_id or project_id'}), 400
12
+ user_id = int(data.get('user_id'))
13
+ project_id = int(data.get('project_id'))
14
+
15
+ mano = await user.find(f'p{user_id}{project_id}', project=True)
16
+ if mano:
17
+ return jsonify({'message': mano}), 200
18
+ return jsonify({'message': 'Cannot find the project!'}), 400
OneApi/api/set_repo.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ set_repo_bp = Blueprint('set_repo', __name__)
7
+
8
+ @app.route('/set_repo/', methods=['POST'])
9
+ async def set_repo():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data and not 'project_id' in data and not 'repo_id' in data: return jsonify({'error': 'missing user_id or project_id or repo_id'}), 400
12
+ user_id = int(data.get('user_id'))
13
+ project_id = int(data.get('project_id'))
14
+ repo_id = int(data.get('repo_id'))
15
+
16
+ mano = await user.set_repo(user_id, project_id, repo_id)
17
+ if mano == 'ok':
18
+ return jsonify({'message': mano}), 200
19
+ elif 'Error' in str(mano):
20
+ return jsonify({'error': mano}), 400
21
+ return jsonify({'message': mano}), 400
OneApi/api/user_info.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from ..database import *
2
+ from quart import *
3
+ from .. import *
4
+
5
+ user = user()
6
+ user_info_bp = Blueprint('user_info', __name__)
7
+
8
+ @app.route('/user_info/', methods=['POST'])
9
+ async def user_info():
10
+ data = await request.get_json()
11
+ if not data or not 'user_id' in data: return jsonify({'error': 'missing user_id'}), 400
12
+ user_id = int(data.get('user_id'))
13
+ d = await user.user_info(user_id)
14
+ if d == 'not exists': return jsonify({'message': "user not found"}), 404
15
+ elif 'error' in d: return jsonify({'error': d}), 400
16
+ return jsonify({'message': d}), 200
OneApi/database/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .user import *
OneApi/database/methods/__init__.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .user_info import UserInfo
2
+ from .get_repos import GetRepos
3
+ from .delete_user import DeleteUser
4
+ from .disconnect_git import DisconnectGit
5
+ from .set_repo import SetRepo
6
+ from .add_log import addLog
7
+ from .get_repo import GetRepo
8
+
9
+ class Methods(
10
+ UserInfo,
11
+ GetRepos,
12
+ DeleteUser,
13
+ DisconnectGit,
14
+ SetRepo,
15
+ addLog,
16
+ GetRepo,
17
+ ):
18
+ pass
OneApi/database/methods/add_log.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ import logging
3
+
4
+ class addLog:
5
+ async def add_log(self, user_id: int, project_id: int, log_text: str):
6
+ try:
7
+ db, cb = self.db, self.cb
8
+ user = await self.find(user_id)
9
+ project = await db.find_one({"_id": f"p{user_id}{project_id}"})
10
+ if not user: return 'not exists'
11
+ elif not project: return 'Project not found'
12
+
13
+ log = project.get('logs')[-10000:]
14
+ log += f"{self.lf}: {log_text}"
15
+
16
+ await db.update_one(
17
+ {"_id": f"p{user_id}{project_id}"},
18
+ {"$set": {
19
+ "logs": log
20
+ }}
21
+ )
22
+ return True
23
+ except Exception as r:
24
+ logging.error(traceback.format_exc())
25
+ return False
OneApi/database/methods/delete_user.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ import logging
3
+
4
+ class DeleteUser:
5
+ async def delete_user(self, user_id: int):
6
+ try:
7
+ user = await self.find(user_id)
8
+ if not user: "not exists"
9
+ db, cb = self.db, self.cb
10
+ await db.update_one({"_id": 1}, {"$pull": {"users": user_id}})
11
+ await db.delete_one({"_id": user_id})
12
+ for x in user.get('projects'):
13
+ if x.get('project_id'):
14
+ try: await db.delete_one({"_id": f"{user_id}{int(x.get('project_id'))}"})
15
+ except: pass
16
+ try:
17
+ await cb.update_one({"_id": 1}, {"$pull": {"users": user_id}})
18
+ await cb.delete_one({"_id": user_id})
19
+ except Exception as e: logging.error("Error on deleting user callback data ^_^: {user_id}, {e}")
20
+ return True
21
+ except Exception as e:
22
+ logging.error(traceback.format_exc())
23
+ return f"Error: {e}"
24
+
25
+
OneApi/database/methods/disconnect_git.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ import logging
3
+
4
+ class DisconnectGit:
5
+ async def disconnect_git(self, user_id: int):
6
+ try:
7
+ user = await self.find(user_id, check=True)
8
+ if not user: "not exists"
9
+ db, cb = self.db, self.cb
10
+ await cb.update_one({"_id": 1}, {"$pull": {"users": user_id}})
11
+ await cb.delete_one({"_id": user_id})
12
+ return True
13
+ except Exception as e:
14
+ logging.error(traceback.format_exc())
15
+ return f"Error: {e}"
16
+
OneApi/database/methods/get_repo.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import traceback
3
+
4
+ class GetRepo:
5
+ async def get_repo(self, user_id: int, repo_id: int):
6
+ try:
7
+ db, cb = self.db, self.cb
8
+ user = await self.find(user_id)
9
+ if not user: return 'not exists'
10
+ hmm = await self.get_repos(user_id)
11
+
12
+ if not hmm: return False
13
+
14
+ yes = False
15
+ for x in hmm:
16
+ if int(x.get('id', 0)) == int(repo_id):
17
+ yes = x
18
+ break
19
+ if yes: return yes
20
+ except: logging.error(traceback.format_exc())
21
+ return False
OneApi/database/methods/get_repos.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ import logging
3
+ import httpx
4
+
5
+ class GetRepos:
6
+ async def get_repos(self, user_id: int):
7
+ try:
8
+ db, cb = self.db, self.cb
9
+ user = await self.find(user_id)
10
+ if not user: return 'not exists'
11
+ installation_id = (await cb.find_one({"_id": int(user_id)})).get('installation_id', None)
12
+ if not installation_id: return "not exists"
13
+ token = await self.gen_token(installation_id)
14
+ url = "https://api.github.com/installation/repositories?page=1"
15
+ headers = {
16
+ "Authorization": f"Bearer {token}",
17
+ "Accept": "application/vnd.github+json"
18
+ }
19
+ async with httpx.AsyncClient() as mano:
20
+ r = await mano.get(url, headers=headers)
21
+ if r.status_code == 200:
22
+ data = r.json()
23
+ if not data.get("repositories"): return []
24
+ ily = []
25
+ for x in data.get("repositories"):
26
+ name, full_name, id = x.get('name'), x.get('full_name'), x.get('id')
27
+ ily.append({'name': name, 'id': id, 'full_name': full_name})
28
+ try: pages = list(range(2, int(str(r.headers.get('Link', ''))[126])+1))
29
+ except Exception as w:
30
+ logging.error(f"GetRepos 30: {w}")
31
+ pages = []
32
+ for x in pages:
33
+ url = f"https://api.github.com/installation/repositories?page={x}"
34
+ k = await mano.get(url, headers=headers)
35
+ data = k.json()
36
+ if k.status_code == 200 and data.get("repositories"):
37
+ for x in data["repositories"]:
38
+ name, full_name, id = x.get('name'), x.get('full_name'), x.get('id')
39
+ ily.append({'name': name, 'id': id, 'full_name': full_name})
40
+ return ily
41
+ else:
42
+ logging.info(f"Failed to get repos of user: {user_id}: {r.text}")
43
+ return "failed"
44
+ except Exception as w:
45
+ logging.error(traceback.format_exc())
46
+ return f"Error: {w}"
OneApi/database/methods/set_repo.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ import logging
3
+
4
+ class SetRepo:
5
+ async def set_repo(self, user_id: int, project_id: int, repo_id: int):
6
+ try:
7
+ db, cb = self.db, self.cb
8
+ user = await self.find(user_id)
9
+ project = await db.find_one({"_id": f"p{user_id}{project_id}"})
10
+ if not user: return 'not exists'
11
+ elif not project: return 'Project not found'
12
+
13
+ hmm = await self.get_repos(user_id)
14
+ if not hmm:
15
+ logging.info(f"Set repo 16: {hmm}")
16
+ return 'Repo not found'
17
+
18
+ yes = False
19
+ for x in hmm:
20
+ if int(x.get('id', 0)) == int(repo_id):
21
+ yes = True
22
+ name = x.get('name')
23
+ break
24
+ if not yes:
25
+ logging.info("Cannot find project")
26
+ return 'Repo not found'
27
+
28
+ log = project.get('logs')
29
+ log += f"{self.lf}: Repo linked successfully"
30
+
31
+ await db.update_one(
32
+ {"_id": f"p{user_id}{project_id}"},
33
+ {"$set": {
34
+ "logs": log,
35
+ "repo": repo_id,
36
+ "repo_name": name
37
+ }}
38
+ )
39
+ return 'ok'
40
+ except Exception as e:
41
+ logging.error(traceback.format_exc())
42
+ return f"Error: {e}"
43
+
OneApi/database/methods/user_info.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ import logging
3
+ import httpx
4
+
5
+ class UserInfo:
6
+ async def user_info(self, user_id):
7
+ try:
8
+ from ..user import db
9
+ user = await self.find(user_id)
10
+ if not user: return "not exists"
11
+ data = {
12
+ "name": user.get('name'),
13
+ "coins": user.get('coins'),
14
+ "projects": len(user.get('projects')),
15
+ "git": user.get('git')
16
+ }
17
+ return data
18
+ except Exception as w:
19
+ logging.error(traceback.format_exc())
20
+ return f'Error: {w}'
OneApi/database/user.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .. import DATABASE
2
+ import logging
3
+ import traceback
4
+ from .methods import *
5
+ import httpx
6
+ from ..others import *
7
+
8
+ db = DATABASE['user_nelskk']
9
+
10
+ class user(Methods):
11
+ def __init__(self):
12
+ self.db = db
13
+ self.cb = DATABASE['cb']
14
+ self.gen_token = gen_token
15
+ self.lf = "\n[ElevenHost]"
16
+ async def find(self, user_id, project=False, check=False):
17
+ try:
18
+ if project:
19
+ return await db.find_one({"_id": str(user_id)})
20
+ elif check:
21
+ if await db.find_one({"_id": int(user_id)}) and await self.cb.find_one({"_id": user_id}):
22
+ return True
23
+ return False
24
+ user = await db.find_one({"_id": int(user_id)})
25
+ return user
26
+ except Exception as w:
27
+ e = traceback.format_exc()
28
+ logging.error(e)
29
+ return f"Error: {w}"
30
+ async def create(self, name: str, user_id: int):
31
+ try:
32
+ if await self.find(user_id): return "exists"
33
+ if not await self.cb.find_one({"_id": user_id}): return "Not connected"
34
+ url = "https://api.github.com/installation/repositories"
35
+ installation_id = await self.cb.find_one({"_id": user_id})
36
+ if installation_id and installation_id.get('installation_id'):
37
+ token = await self.gen_token(installation_id.get('installation_id'))
38
+ if not token: return "Not connected"
39
+ else: return "Not connected"
40
+
41
+ headers = {
42
+ "Authorization": f"Bearer {token}",
43
+ "Accept": "application/vnd.github+json"
44
+ }
45
+
46
+ async with httpx.AsyncClient() as client:
47
+ response = await client.get(url, headers=headers)
48
+ if response.status_code == 200:
49
+ data = response.json()
50
+ if data["repositories"]:
51
+ owner = data["repositories"][0]["owner"]
52
+ owner = owner["login"]
53
+ else: owner = 'CannotFound'
54
+ else:
55
+ logging.warn(f"GitHub doesn't give 200 status code: {response.text}")
56
+ return "Not connected"
57
+
58
+ await db.update_one({"_id": 1}, {"$addToSet": {"users": user_id}}, upsert=True)
59
+ await db.update_one(
60
+ {"_id": user_id},
61
+ {"$set": {"name": name, "coins": 0, "projects": [], 'latest_project': 0, 'git': owner}},
62
+ upsert=True
63
+ )
64
+
65
+ return 'ok'
66
+
67
+ except Exception as w:
68
+ e = traceback.format_exc()
69
+ logging.error(e)
70
+ return f"Error: {w}"
71
+
72
+ async def get_projects(self, user_id: int):
73
+ try:
74
+ if not await self.find(user_id): return "not exists"
75
+ user = await self.find(user_id)
76
+ if user.get('projects'):
77
+ return user.get('projects')
78
+ return 'projects not found'
79
+ except Exception as oh:
80
+ e = traceback.format_exc()
81
+ logging.error(e)
82
+ return f"Error: {oh}"
83
+
84
+ async def create_project(self, name: str, user_id: int, plan: str):
85
+ try:
86
+ user = await self.find(user_id)
87
+ if not user: return "not exists"
88
+ elif name and len(name) < 4:
89
+ return 'Name too short'
90
+
91
+ name, latest_project = name[:15], int(user.get('latest_project', 0)) + 1
92
+ coins = user.get('coins', 0)
93
+
94
+ if any(proj.get('name') == name for proj in user.get('projects', [])):
95
+ return "Name already used"
96
+
97
+ if plan == 'free':
98
+ plan_price = 0
99
+ elif plan == 'basic':
100
+ plan_price = 99
101
+ elif plan == 'advance':
102
+ plan_price = 199
103
+ elif plan == 'pro':
104
+ plan_price = 269
105
+ else: return 'Plan not found'
106
+ if coins < plan_price:
107
+ return 'insufficient coins'
108
+
109
+ if plan_price != 0: await db.update_one({"_id": user_id}, {"$set": {'coins': coins-plan_price}})
110
+
111
+ await db.update_one(
112
+ {"_id": f'p{user_id}{latest_project}'},
113
+ {"$set": {
114
+ "name": name,
115
+ "id": latest_project,
116
+ "plan": plan,
117
+ "ram": 10000,
118
+ "rom": 100000000,
119
+ "repo": 0,
120
+ "repo_name": 'Not set',
121
+ "apt-allowed": False,
122
+ "language": 'None',
123
+ "logs": f"[ElevenHost]: Project successfully created!"
124
+ }},
125
+ upsert=True
126
+ )
127
+ await db.update_one(
128
+ {"_id": user_id},
129
+ {"$addToSet": {
130
+ "projects": {
131
+ 'name': name,
132
+ 'project_id': latest_project
133
+ }
134
+ }}
135
+ )
136
+ await db.update_one({"_id": user_id}, {"$set": {"latest_project": latest_project}})
137
+ return 'ok'
138
+ except Exception as e:
139
+ logging.error(traceback.format_exc())
140
+ return f'Error: {e}'
141
+
142
+ async def delete_project(self, user_id: int, project_id: int):
143
+ try:
144
+ user = await self.find(user_id)
145
+ if not user:
146
+ return "not exists"
147
+ if not user.get('projects'):
148
+ return "Project not found"
149
+ if not any(proj.get('project_id') == project_id for proj in user.get('projects', [])):
150
+ return "Project not found"
151
+ await db.delete_one({"_id": f"p{user_id}{project_id}"})
152
+ await db.update_one(
153
+ {"_id": user_id},
154
+ {"$pull": {"projects": {"project_id": project_id}}}
155
+ )
156
+ return "ok"
157
+ except Exception as e:
158
+ logging.error(traceback.format_exc())
159
+ return f"Error: {e}"
OneApi/deployment/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from .host import Host
2
+ class Methods(
3
+ Host
4
+ ):
5
+ pass
OneApi/deployment/deployment.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from .. import *
2
+ from . import Methods
3
+ from ..database import user
4
+
5
+ class Deployment(Methods):
6
+ def __init__(self):
7
+ self.lf = "\n[ElevenHost]"
8
+ self.database = user()
9
+ self.cb = DATABASE['cb']
OneApi/deployment/host.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .. import *
2
+ import logging
3
+ import traceback
4
+ import asyncio
5
+ import aiofiles
6
+ import aiofiles.os
7
+ import yaml
8
+
9
+ async def check_yaml(data):
10
+ f = "FileFormatInvalidError:"
11
+ if not data.get('language'):
12
+ return f'{f} Project language not found in ElevenHost.yaml'
13
+ elif not data.get('version'):
14
+ return f'{f} Project language version not found in ElevenHost.yaml'
15
+ elif not data.get('build'):
16
+ return f'{f} Build not found on ElevenHost.yaml'
17
+ elif not data.get('packages'):
18
+ return f'{f} Packages not found in ElevenHost.yaml'
19
+ elif not data.get("start"):
20
+ return f'{f} start not found in ElevenHost.yaml'
21
+ else: return True
22
+
23
+ async def create_docker(data):
24
+ dockerfile = f"FROM {data.get('language')}:{data.get('version')}\n\n"
25
+ dockerfile += ''.join([f"RUN {x}\n\n" for x in data.get('build')])
26
+ dockerfile += ''.join([f"RUN apt-get install {x} -y\n\n" for x in data.get('packages')])
27
+ dockerfile += f"COPY . /app/\n\nCMD {data.get('start')[0]}\n"
28
+ return dockerfile
29
+
30
+ class Host:
31
+ async def host(self, user_id: int, project_id: int):
32
+ database = self.database
33
+ user = await database.find(user_id)
34
+ project = await database.find(f"p{user_id}{project_id}", project=True)
35
+ if not user: return 'not exists'
36
+ elif not project: return 'Project not found'
37
+ repo_id = project.get('repo', 0)
38
+ repo = await database.get_repo(user_id, repo_id)
39
+ if not repo: return "Repo not found"
40
+
41
+ installation_id = (await self.cb.find_one({"_id": int(user_id)})).get('installation_id', None)
42
+ if not installation_id: return "not exists"
43
+ token = await database.gen_token(installation_id)
44
+
45
+ try:
46
+ folder = f"deployment{user_id}"
47
+ await database.add_log(user_id, project_id, "Clonning repo from github...")
48
+ await run(f"rm -rf {folder}")
49
+ await run(f"mkdir {folder}")
50
+ ok = await run(f"cd {folder} && git clone https://x-access-token:{token}@github.com/{repo.get('full_name')}/")
51
+ repo_folder = f"{folder}/{repo.get('name')}"
52
+
53
+ if not await aiofiles.os.path.isdir(repo_folder):
54
+ await database.add_log(user_id, project_id, f"Error on clonning repo: {ok}")
55
+ return 'Failed to host repo'
56
+ ls = await run(f"ls {repo_folder}")
57
+
58
+ await database.add_log(
59
+ user_id,
60
+ project_id,
61
+ f"Successfully clonned repo!, Files found in repo: {len(ls.split('\n')) if '\n' in ls else 0}"
62
+ )
63
+
64
+ if not await aiofiles.os.path.isfile(f"{repo_folder}/ElevenHost.yaml"):
65
+ await database.add_log(
66
+ user_id,
67
+ project_id,
68
+ f"Error:\nCannot find ElevenHost.yaml on your repo"
69
+ )
70
+ return "ElevenHost.yaml not found"
71
+
72
+ async with aiofiles.open(f"{repo_folder}/ElevenHost.yaml", mode='r') as mano:
73
+ ctx = mano.read()
74
+ data = yaml.safe_load(ctx)
75
+ chk = await check_yaml(data)
76
+
77
+ if not chk is True:
78
+ await database.add_log(user_id, project_id, chk)
79
+ return chk
80
+
81
+ return True
82
+ except Exception as w:
83
+ logging.error(traceback.format_exc())
84
+ return f"Error: {w}"
85
+
86
+
87
+
OneApi/others/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .gen_token import gen_token
OneApi/others/gen_token.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import jwt
2
+ from time import time
3
+ import httpx
4
+
5
+ with open("mano.pem", "r") as f:
6
+ PRIVATE_KEY = f.read()
7
+ APP_ID = "1109508"
8
+
9
+ async def gen_token(installation_id):
10
+ payload = {
11
+ "iat": int(time()),
12
+ "exp": int(time()) + 60,
13
+ "iss": APP_ID,
14
+ }
15
+ jwt_token = jwt.encode(payload, PRIVATE_KEY, algorithm="RS256")
16
+ url = f"https://api.github.com/app/installations/{installation_id}/access_tokens"
17
+ headers = {
18
+ "Authorization": f"Bearer {jwt_token}",
19
+ "Accept": "application/vnd.github+json",
20
+ }
21
+ async with httpx.AsyncClient() as client:
22
+ response = await client.post(url, headers=headers)
23
+ if response.status_code == 201:
24
+ return response.json().get("token")
25
+ return None
docker-compose.yml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ oneapi:
5
+ build: .
6
+ ports:
7
+ - "8080:8080"
8
+ environment:
9
+ - MONGO_DB_URL=mongodb://mongo:27017/OneApi
10
+ - API_ID=${API_ID:-29764570}
11
+ - API_HASH=${API_HASH:-7676192e491329a1b859b2184e5d7823}
12
+ - TOKEN=${TOKEN:-BQCDh4MAZuO8dsEXNE9pCZtV297oEptGvaTC75QL9GSgnhG8eZP4GVWQqPCzbKxyhN8iCsDX2HG72JIC_LVOYL6-aB3TcuY9eafbv2sKq-usHKOUA8lXf1RUzkaeYA1QNvjSU9hZrKCbrH6NtfuPzkFQeRCYhK-z2GDekhykPqLEHJu0hewOYtdwbC_om47iF3rUL94Wi3UOhAVzr_IZeklt8IIbL6stzR7dIce17ZbIlNGsVwZr6qMgBh-CYl4A0XlCh_iuMyRAmYHJ9nBQR-OhxuwewMDl9R8AvvHxnE3KYEbX2NGTFaOacWg5mtd4cm8OIf8ese4oC-TnspkFSmUPEQwNXwAAAAG1SBMOAQ}
13
+ - DEVS=${DEVS:-5965055071}
14
+ - PORT=8080
15
+ depends_on:
16
+ - mongo
17
+ volumes:
18
+ - ./logs:/app/logs
19
+ restart: unless-stopped
20
+
21
+ mongo:
22
+ image: mongo:6.0
23
+ ports:
24
+ - "27017:27017"
25
+ environment:
26
+ - MONGO_INITDB_DATABASE=OneApi
27
+ volumes:
28
+ - mongo_data:/data/db
29
+ restart: unless-stopped
30
+
31
+ volumes:
32
+ mongo_data:
mano.pem ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEpAIBAAKCAQEA1gNfDkAFX+K/ug05GXdigs4sHrL/ZDSV2Vj4h8uZb6UXJeoe
3
+ I6O2kjKC5Zbo2F+JwbC0nhnzhlngUadjUWXJtnkANyEPk+Hxk56qIo2akRN8KHEL
4
+ aWpXPznwj0ZxP4s3hEwgmDc7n5Kpl9w8nYT6MAUuyB2NZ6E/dRTPU6NHDyuf0yhS
5
+ h98A2ZXcqWHrwtVUHq/I4oEAfu3xvUhoYeODS5MrJV2oLy2crXPUb2t1/AyIl5q4
6
+ 9B3Dj4UYKZTEEDUjCZ+oueo8XDA5xCv8WYYsdYf484lf3po8f4yLBEI2i9aWGnEs
7
+ enWsOI65MYyvXagUbzFyN0XnZNNp3T0xgvoJMwIDAQABAoIBAEywEJPOpR5i5kkJ
8
+ C/jwKsCsmGq3wYRqw3eKxiQC9QxooA7aAcrLk1R3/SfAF9fRBE//vfkZW4Y9FoCr
9
+ 9o7oZouYeFdI5YgcYrB/HoAbNdPeo5LqTyiLDpB9dpIgr9wRSueBT/y7bgYUS+k6
10
+ 5g2b5ProIIdc75q+0TpnJpPV4lSwqWTt6IcuXadx/YdgFLtfa07z1mMwBUQi/GXZ
11
+ kjJkpTNG22pItP1oYSY22EfuIFYkmsx2c44VT61D/Xa01ABk4pOSYZzQXePqymG5
12
+ qI1w7SsuOFQVZIGYuiM8fBBv4Yd9MyJ4KBWG24H2TFw0XjiLmQgYBWuv15foSujv
13
+ 7+z2s6ECgYEA7TmPTShVj4DrGiSsGjgYbHTXybWdxdDnP7b+39/e2tFFax+n06sP
14
+ 1YzWWhQI40uZ0kyCLLiSS6arxhjw9swzAet2NsN+k9u72Qz/Y/XIVT8mmXBc+4I3
15
+ 2YwJU0cPx2unGjUHYx9Am+23o3KHceIFDtyAsljBiJ0CAuTbg9r+APcCgYEA5vOE
16
+ YV23spoe6SME9XpMKLHreSWUWCeMVhkPJZIIlkCHD2m8o+sB1+MApnRBvHWHU5sC
17
+ OOYzt7fMQM/c2aLLSVwGl7Be5XURBcBq984pxq9uolUb0OcTYPIh23ZtlV+Zi1Xr
18
+ b/42DiWVIVFN8gmt59adPe6X3n/1pnHJwIbnZqUCgYEAyZpxPpFYpWxaYQ1pdZ7W
19
+ otVpzfKa8tJmtK9AS+Jl8nCHHlL4vdpSypm2UTdVllVZlG+Q8ZCqQ8CRmvj3T8aa
20
+ UrdY75GUsPO84Ok64iiu6EOS+jOT0esIq8lm428w6bmDebI3ZPXaYqnTtwRON2pu
21
+ AgNDHE5xqzhDzVHRfG1QEGECgYBG5/L31cclbY4Z8+d82nxxbhamjjQaUKIUeQMe
22
+ fNRoFQ2iXMtO5EMfnhFACad5DfhrYcbv4zVzrVlneKoMo5+YOUnI3px0BFoiku4E
23
+ gOZwmsHz0v+ERr27YPumHpkMaFqC3fE35CuCcmVz4jt1GSWsbUa/kfZMmKq53Gud
24
+ 0Y1QBQKBgQCMdt81IsLWCTUQI09Y+9tq/9CqGOUhRGXwG9RCaWrqBBLWWgR8kQVK
25
+ pYdR2MlqHpwywcOAhlOU7r0Cmbonf8cnZuFv6FMI405KExSMIUyhhrbDbYwPNEUo
26
+ ODb/k7oa2AanEasVm8uQgoA/RSNA1zyzFZ8tkFDJ1V6CSQgzAkLAXg==
27
+ -----END RSA PRIVATE KEY-----
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ quart
2
+ motor==3.6.0
3
+ pymongo[srv]
4
+ kurigram
5
+ TgCrypto
6
+ quart-cors
7
+ cryptography
8
+ pyjwt
9
+ aiofiles
10
+ pyyaml
variables.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ VAR_TOKEN = "8185712635:AAFqz_RmsleAbfSeVw--SGw5PaWQS3Cqan0"
2
+ VAR_MONGO_DB_URI = "mongodb+srv://xdragxt:[email protected]/?retryWrites=true&w=majority&appName=dragtest"
3
+ VAR_API_ID = 21188444
4
+ VAR_API_HASH = "031ff911c40173e28290e2f44fcb4b56"
5
+ VAR_DEVS = 7361622601
6
+