diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index a5f1c1e..2df44d0 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -10,7 +10,7 @@ on: jobs: Build Master: - runs-on: ubuntu-latest + runs-on: [ubuntu-latest, arm] steps: - name: Checkout uses: actions/checkout@v2 @@ -51,7 +51,7 @@ jobs: Build Bot: - runs-on: ubuntu-latest + runs-on: [ubuntu-latest, arm] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 83fd30f..e5ea801 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -8,7 +8,7 @@ on: jobs: Build Master: - runs-on: ubuntu-latest + runs-on: [ubuntu-latest,arm] steps: - name: Checkout uses: actions/checkout@v2 @@ -34,7 +34,7 @@ jobs: docker push git.woodburn.au/nathanwoodburn/hnshosting-master:release Build Bot: - runs-on: ubuntu-latest + runs-on: [ubuntu-latest,arm] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/discord-bot/bot.py b/discord-bot/bot.py index e0da690..cf7fa15 100644 --- a/discord-bot/bot.py +++ b/discord-bot/bot.py @@ -51,6 +51,7 @@ async def listworkers(ctx): await ctx.response.send_message(f"Error listing workers\n" + r.text,ephemeral=True) else: await ctx.response.send_message("You do not have permission to use this command",ephemeral=True) + update_bot_status() @tree.command(name="licence", description="Gets a licence key") async def license(ctx): @@ -104,6 +105,7 @@ async def createsite(ctx, domain: str, licence: str = None): await ctx.response.send_message(f"Error creating site\n" + json['error']) else: await ctx.response.send_message(f"Error creating site\n" + r.text) + update_bot_status() @tree.command(name="siteinfo", description="Get info about a WordPress site") @@ -128,6 +130,17 @@ async def check_site_ready(domain): return False else: return False + +def get_site_count(): + r = requests.get(f"http://{Master_IP}:{Master_Port}/site-count") + if r.status_code == 200: + return r.text + else: + return "Error getting site count\n" + r.text + +def update_bot_status(): + site_count = get_site_count() + client.loop.create_task(client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="over " + site_count + " wordpress sites"))) # When the bot is ready @client.event @@ -135,6 +148,9 @@ async def on_ready(): global ADMINID ADMINID = client.application.owner.id await tree.sync() - await client.loop.create_task(client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="over HNSHosting wordpress"))) + + # Get the number of sites + site_count = get_site_count() + await client.loop.create_task(client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="over " + site_count + " wordpress sites"))) client.run(TOKEN) \ No newline at end of file diff --git a/master/main.py b/master/main.py index bcdabd7..96575b9 100644 --- a/master/main.py +++ b/master/main.py @@ -206,6 +206,7 @@ def list_workers(): @app.route('/site-info', methods=['GET']) def site_status(): domain = request.args.get('domain') + domain = domain.lower() if domain == None: return jsonify({'error': 'Invalid domain', 'success': 'false'}) @@ -236,6 +237,7 @@ def site_status(): @app.route('/info') def site_status_human(): domain = request.args.get('domain') + domain = domain.lower() if domain == None: return "

Invalid domain

" @@ -251,7 +253,7 @@ def site_status_human(): # Get worker ip ip = workerIP_PRIV(worker) - # Get TLSA record + # Get TLSA record resp=requests.get("http://"+ip + ":5000/tlsa?domain=" + domain,timeout=2) json = resp.json() publicIP = workerIP(worker) @@ -265,6 +267,7 @@ def site_status_human(): @app.route('/tlsa', methods=['GET']) def tlsa(): domain = request.args.get('domain') + domain = domain.lower() if domain == None: return jsonify({'error': 'Invalid domain', 'success': 'false'}) @@ -401,7 +404,7 @@ def workerIP_PRIV(worker): ip = None for line in workers_file.readlines(): if worker == line.split(':')[0]: - ip = line.split(':')[2].strip('\n') + ip = line.split(':')[1].strip('\n') break workers_file.close() @@ -419,7 +422,7 @@ def workerIP(worker): ip = None for line in workers_file.readlines(): if worker == line.split(':')[0]: - ip = line.split(':')[1].strip('\n') + ip = line.split(':')[2].strip('\n') break workers_file.close() @@ -443,13 +446,127 @@ def home(): return render_template('index.html', site_count = str(len(sites))) # Register page -@app.route('/register') +@app.route('/register', methods=['GET']) def register(): buy_licence_link = os.getenv('BUY_LICENCE_LINK') - # Show register template - return render_template('register.html', buy_licence_link=buy_licence_link) + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="") + +@app.route('/register', methods=['POST']) +def register_post(): + buy_licence_link = os.getenv('BUY_LICENCE_LINK') + if 'licence' not in request.form: + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No licence key provided") + + licence_key = request.form['licence'] + # Check if licence key is valid + key_file = open('/data/licence_key.txt', 'r') + valid_key = False + for line in key_file.readlines(): + if licence_key == line.strip('\n'): + valid_key = True + break + key_file.close() + if not valid_key: + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="Invalid licence key") + + # Get domain + domain = request.form['domain'] + if domain == None: + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No domain provided") + # Check if domain already exists + if site_exists(domain): + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="Domain already exists") + + # Check if domain contains http:// or https:// + if domain.startswith("http://") or domain.startswith("https://"): + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="Domain should not contain http:// or https://") + + # Set domain to lowercase + domain = domain.lower() + + # Check if worker file exists + workers = None + try: + worker_file = open('/data/workers.txt', 'r') + workers = worker_file.readlines() + worker_file.close() + except FileNotFoundError: + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No workers available\nPlease contact support") + + # Get a worker that has available slots + worker = None + for line in workers: + if not line.__contains__(':'): + continue + ip = line.split(':')[1].strip('\n') + resp=requests.get("http://"+ip + ":5000/status",timeout=2) + if (resp.status_code == 200): + if resp.json()['availability'] == True: + worker = line + break + + if worker == None: + return render_template('register.html', buy_licence_link=buy_licence_link, ERROR_MESSAGE="No workers available\nPlease contact support") + + # Delete licence key + key_file = open('/data/licence_key.txt', 'r') + lines = key_file.readlines() + key_file.close() + key_file = open('/data/licence_key.txt', 'w') + for line in lines: + if line.strip("\n") != licence_key: + key_file.write(line) + key_file.close() + + # Add domain to file + sites_file = open('/data/sites.txt', 'a') + sites_file.write(domain + ':' + worker.split(':')[0] + '\n') + sites_file.close() + + # Send worker request + requests.post("http://"+ worker.split(':')[1].strip('\n') + ":5000/new-site?domain=" + domain) + + return redirect('/success?domain=' + domain + '&status=creating') + +@app.route('/success') +def success(): + if 'domain' not in request.args: + return redirect('/') + domain = request.args.get('domain') + domain = domain.lower() + if not site_exists(domain): + return render_template('success.html', message="Error: Domain does not exist\nPlease contact support") + + if 'status' not in request.args: + # Get worker + worker = site_worker(domain) + if worker == None: + return render_template('success.html', message="Error: Domain does not exist\nPlease contact support") + # Get worker ip + ip = workerIP_PRIV(worker) + + # Get TLSA record + resp=requests.get("http://"+ip + ":5000/tlsa?domain=" + domain,timeout=2) + json = resp.json() + publicIP = workerIP(worker) + + if "tlsa" in json: + tlsa = json['tlsa'] + return render_template('success.html', message="Success\nDomain: " + domain + "\nIP: " + publicIP + "\nTLSA: " + tlsa + "\nMake sure to add the TLSA record to `_443._tcp." + domain + "` or `*." + domain + "`") + else: + return render_template('success.html', message="Success\nDomain: " + domain + "\nIP: " + publicIP + "\nTLSA: Pending\nNo TLSA record found") + + elif request.args.get('status') == 'creating': + return render_template('success.html') + + +@app.route('/site-count') +def site_count_route(): + return str(get_sites_count()) + + # Admin page @app.route('/admin') @@ -604,7 +721,7 @@ def addsite(): if domain.startswith("http://") or domain.startswith("https://"): return jsonify({'error': 'Domain should not contain http:// or https://', 'success': 'false'}) - + domain = domain.lower() # Check if worker file exists workers = None try: diff --git a/master/templates/assets/js/status_update.js b/master/templates/assets/js/status_update.js new file mode 100644 index 0000000..0738dca --- /dev/null +++ b/master/templates/assets/js/status_update.js @@ -0,0 +1,10 @@ +// Refresh page without status arg + +// Wait 10 seconds +setTimeout(function() { + // Refresh page + // Get domain from param + var domain = urlParams.get('domain'); + + window.location = "https://hnshosting.au/success?domain=" + domain; +}, 10000); \ No newline at end of file diff --git a/master/templates/register.html b/master/templates/register.html index f89496a..9dec5a3 100644 --- a/master/templates/register.html +++ b/master/templates/register.html @@ -41,10 +41,12 @@
-
+
-
+
+

{{ERROR_MESSAGE}}

+

Don't have a licence?
Click here to buy one

diff --git a/master/templates/success.html b/master/templates/success.html new file mode 100644 index 0000000..f2cb7f3 --- /dev/null +++ b/master/templates/success.html @@ -0,0 +1,58 @@ + + + + + + + Home - HNSHosting + + + + + + + + + + + + + + +
+
+
+
+
+

Success

+

Your site is installing.
Please wait...

+
+

{{message}}

+
+
+
+
+
+
+
+
+

Copyright © 2023 HNSHosting

+
+
+
+ + + + + + \ No newline at end of file