initial working version
This commit is contained in:
		
							parent
							
								
									061959cf6f
								
							
						
					
					
						commit
						44a7cd0b82
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| venv/ | ||||
| config.py | ||||
							
								
								
									
										17
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| { | ||||
|     // Use IntelliSense to learn about possible attributes. | ||||
|     // Hover to view descriptions of existing attributes. | ||||
|     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|     "version": "0.2.0", | ||||
|     "configurations": [ | ||||
|         { | ||||
|             "name": "Python Debugger: Current File", | ||||
|             "type": "debugpy", | ||||
|             "request": "launch", | ||||
|             "program": "${file}", | ||||
|             "console": "integratedTerminal", | ||||
|             "justMyCode": false, | ||||
|             "args": ["--host=0.0.0.0"] | ||||
|         } | ||||
|     ] | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								__pycache__/config.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								__pycache__/config.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										73
									
								
								app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								app.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| # app.py | ||||
| from flask import Flask, render_template, request, redirect, url_for, session, flash | ||||
| import requests.auth | ||||
| from lib.datetime import filter_accounts_current_month | ||||
| from lib.reqs import (get_urls, get_user_accounts) | ||||
| import requests | ||||
| import base64 | ||||
| from flask import Flask | ||||
| from config import DevelopmentConfig  # or ProductionConfig | ||||
| 
 | ||||
| app = Flask(__name__) | ||||
| app.config.from_object(DevelopmentConfig)  # Use DevelopmentConfig or ProductionConfig as needed | ||||
| 
 | ||||
| @app.route('/') | ||||
| def home(): | ||||
|     # If the user is logged in, redirect to a protected page like /accounts | ||||
|     if session.get('logged_in'): | ||||
|         base_url = app.config['BASE_URL']  # Access base_url from the config | ||||
|         all_accounts = get_user_accounts(base_url, session['auth_credentials']) | ||||
|         current_month_accounts = filter_accounts_current_month(all_accounts) | ||||
|         return render_template('home.html',  username=session['username'], accounts=get_user_accounts(base_url, session['auth_credentials']), current_month_accounts=current_month_accounts) | ||||
|     return render_template('index.html') | ||||
| 
 | ||||
| @app.route('/login', methods=['POST']) | ||||
| def login(): | ||||
|     username = request.form['username'] | ||||
|     password = request.form['password'] | ||||
|      | ||||
|     # Encode the username and password in Base64 | ||||
|     credentials = f"{username}:{password}" | ||||
|     encoded_credentials = base64.b64encode(credentials.encode()).decode() | ||||
|      | ||||
|     base_url = app.config['BASE_URL']  # Access base_url from the config | ||||
|     login_url = f"{base_url}/Login"  # Construct the full URL | ||||
| 
 | ||||
|     # Send GET request to the external login API with Basic Auth | ||||
|     response = requests.get( | ||||
|         login_url, | ||||
|         auth=requests.auth.HTTPBasicAuth(username, password) | ||||
|     ) | ||||
| 
 | ||||
|     # Check if login was successful | ||||
|     if response.status_code == 200 and response.json().get("auth") == "Success": | ||||
|         # Set session variable to indicate the user is logged in | ||||
|         session['logged_in'] = True | ||||
|         session['username'] = username | ||||
|         session['auth_credentials'] = encoded_credentials | ||||
|         return redirect(url_for('home'))  # Redirect to the Accounts page | ||||
|     else: | ||||
|         # Show error on the login page | ||||
|         error = "Invalid username or password. Please try again." | ||||
|         return render_template('index.html', error=error) | ||||
| 
 | ||||
| @app.route('/urls', methods=['GET']) | ||||
| def urls(): | ||||
|     # Check if the user is logged in | ||||
|     if not session.get('logged_in'): | ||||
|         return redirect(url_for('home')) | ||||
|     # Placeholder content for Accounts page | ||||
|     base_url = app.config['BASE_URL']  # Access base_url from the config | ||||
|     return render_template('urls.html', urls=get_urls(base_url, session['auth_credentials'])) | ||||
| 
 | ||||
| @app.route('/accounts', methods=['GET']) | ||||
| def user_accounts(): | ||||
|     # Check if the user is logged in | ||||
|     if not session.get('logged_in'): | ||||
|         return redirect(url_for('home')) | ||||
|     # Placeholder content for Accounts page | ||||
|     base_url = app.config['BASE_URL']  # Access base_url from the config     | ||||
|     return render_template('user_accounts.html', username=session['username'], user_accounts=get_user_accounts(base_url, session['auth_credentials'])) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     app.run(debug=app.config['DEBUG'], host=app.config['HOST'], port=app.config['PORT']) | ||||
							
								
								
									
										11
									
								
								config.py.sample
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								config.py.sample
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| # config.py | ||||
| 
 | ||||
| class Config: | ||||
|     DEBUG = False | ||||
|     BASE_URL = ''  # Set your base URL here | ||||
| 
 | ||||
| class DevelopmentConfig(Config): | ||||
|     DEBUG = True | ||||
| 
 | ||||
| class ProductionConfig(Config): | ||||
|     BASE_URL = ''  # Production base URL | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/__pycache__/datetime.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/__pycache__/datetime.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										25
									
								
								lib/datetime.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/datetime.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| from datetime import datetime | ||||
| from flask import render_template | ||||
| 
 | ||||
| def filter_accounts_current_month(accounts): | ||||
|     # Get the start and end of the current month | ||||
|     now = datetime.now() | ||||
|     start_of_month = datetime(now.year, now.month, 1) | ||||
|     if now.month == 12: | ||||
|         # If current month is December, next month is January of the next year | ||||
|         start_of_next_month = datetime(now.year + 1, 1, 1) | ||||
|     else: | ||||
|         # Otherwise, next month is just the next month of the same year | ||||
|         start_of_next_month = datetime(now.year, now.month + 1, 1) | ||||
|      | ||||
|     # Convert start and end of the month to epoch timestamps | ||||
|     start_of_month_timestamp = int(start_of_month.timestamp()) | ||||
|     start_of_next_month_timestamp = int(start_of_next_month.timestamp()) | ||||
| 
 | ||||
|     # Filter accounts with expiryDate in the current month | ||||
|     accounts_in_current_month = [ | ||||
|         account for account in accounts | ||||
|         if start_of_month_timestamp <= account['expiaryDate'] < start_of_next_month_timestamp | ||||
|     ] | ||||
| 
 | ||||
|     return accounts_in_current_month | ||||
							
								
								
									
										26
									
								
								lib/reqs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								lib/reqs.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| import requests | ||||
| import json | ||||
| from datetime import datetime | ||||
| 
 | ||||
| 
 | ||||
| def get_urls(base_url, auth: str) -> list: | ||||
|     url = f"{base_url}/getUserAccounts/streams" | ||||
| 
 | ||||
|     payload = {} | ||||
|     headers = {"Authorization": f"Basic {auth}"} | ||||
| 
 | ||||
|     response = requests.request("GET", url, headers=headers, data=payload) | ||||
|     return json.loads(response.text) | ||||
| 
 | ||||
| 
 | ||||
| def get_user_accounts(base_url, auth: str) -> list: | ||||
|     url = f"{base_url}/getUserAccounts" | ||||
| 
 | ||||
|     payload = {} | ||||
|     headers = {"Authorization": f"Basic {auth}"} | ||||
| 
 | ||||
|     response = requests.request("GET", url, headers=headers, data=payload) | ||||
|     res_json = json.loads(response.text) | ||||
|     for account in res_json: | ||||
|         account['expiaryDate_rendered'] = datetime.utcfromtimestamp(account['expiaryDate']).strftime('%d/%m/%Y')   | ||||
|     return res_json | ||||
							
								
								
									
										66
									
								
								templates/home.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								templates/home.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| <!-- templates/index.html --> | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>KTV Manager</title> | ||||
|     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> | ||||
| </head> | ||||
| <body> | ||||
| 
 | ||||
|     <!-- Navbar --> | ||||
|     <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> | ||||
|         <a class="navbar-brand" href="#">KTV Manager</a> | ||||
|         <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> | ||||
|             <span class="navbar-toggler-icon"></span> | ||||
|         </button> | ||||
|         <div class="collapse navbar-collapse" id="navbarNav"> | ||||
|             <ul class="navbar-nav ml-auto"> | ||||
|                 <li class="nav-item"> | ||||
|                     <a class="nav-link" href="/">Home</a> | ||||
|                 </li> | ||||
|                 <li class="nav-item"> | ||||
|                     <a class="nav-link" href="/accounts">Accounts</a> | ||||
|                 </li> | ||||
|                 <li class="nav-item"> | ||||
|                     <a class="nav-link" href="/urls">URLs</a> | ||||
|                 </li> | ||||
|             </ul> | ||||
|         </div> | ||||
|     </nav> | ||||
| 
 | ||||
|     <!-- Main Content --> | ||||
|     <div class="container mt-5"> | ||||
|         <h1>Welcome to KTV Manager {{ username }}</h1> | ||||
|         <span>You have {{accounts|length}} accounts</span> | ||||
|         <h3>Accounts Expiring This Month</h3> | ||||
|         <table class="table table-bordered table-striped"> | ||||
|             <thead class="thead-dark"> | ||||
|                 <tr> | ||||
|                     <th>Stream Name</th> | ||||
|                     <th>Username</th> | ||||
|                     <th>Expiry Date</th> | ||||
|                 </tr> | ||||
|             </thead> | ||||
|             <tbody> | ||||
|                 {% for account in current_month_accounts %} | ||||
|                     <tr> | ||||
|                         <td>{{ account.stream }}</td> | ||||
|                         <td>{{ account.username }}</td> | ||||
|                         <td>{{ account.expiaryDate_rendered }}</td> | ||||
|                     </tr> | ||||
|                 {% endfor %} | ||||
|             </tbody> | ||||
|         </table> | ||||
|     </div> | ||||
| 
 | ||||
|     <footer class="bg-dark text-white text-center py-3 mt-5"> | ||||
|         <p>© 2024 KTV Manager | All rights reserved</p> | ||||
|     </footer> | ||||
| 
 | ||||
|     <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> | ||||
|     <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.0.7/dist/umd/popper.min.js"></script> | ||||
|     <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> | ||||
| </body> | ||||
| </html> | ||||
| @ -21,10 +21,10 @@ | ||||
|                     <a class="nav-link" href="/">Home</a> | ||||
|                 </li> | ||||
|                 <li class="nav-item"> | ||||
|                     <a class="nav-link" href="/accounts">Accounts</a> <!-- Link to the URLs page --> | ||||
|                     <a class="nav-link" href="/accounts">Accounts</a> | ||||
|                 </li> | ||||
|                 <li class="nav-item"> | ||||
|                     <a class="nav-link" href="/urls">URLs</a> <!-- Link to the URLs page --> | ||||
|                     <a class="nav-link" href="/urls">URLs</a> | ||||
|                 </li> | ||||
|             </ul> | ||||
|         </div> | ||||
| @ -33,7 +33,22 @@ | ||||
|     <!-- Main Content --> | ||||
|     <div class="container mt-5"> | ||||
|         <h1>Welcome to KTV Manager</h1> | ||||
|         <!-- <p>This website is built using Flask and Bootstrap. It’s designed to look great on any screen size!</p> --> | ||||
| 
 | ||||
|         <!-- Login Form --> | ||||
|         <form action="/login" method="post" class="mt-3"> | ||||
|             <div class="form-group"> | ||||
|                 <label for="username">Username:</label> | ||||
|                 <input type="text" class="form-control" id="username" name="username" required> | ||||
|             </div> | ||||
|             <div class="form-group"> | ||||
|                 <label for="password">Password:</label> | ||||
|                 <input type="password" class="form-control" id="password" name="password" required> | ||||
|             </div> | ||||
|             <button type="submit" class="btn btn-primary">Login</button> | ||||
|             {% if error %} | ||||
|                 <div class="alert alert-danger mt-3">{{ error }}</div> | ||||
|             {% endif %} | ||||
|         </form> | ||||
|     </div> | ||||
| 
 | ||||
|     <footer class="bg-dark text-white text-center py-3 mt-5"> | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>URLs List</title> | ||||
|     <title>KTVManager</title> | ||||
|     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> | ||||
| </head> | ||||
| <body> | ||||
| @ -53,7 +53,7 @@ | ||||
|     </div> | ||||
| 
 | ||||
|     <footer class="bg-dark text-white text-center py-3 mt-5"> | ||||
|         <p>© 2024 My Site | All rights reserved</p> | ||||
|         <p>© 2024 KTVManager | All rights reserved</p> | ||||
|     </footer> | ||||
| 
 | ||||
|     <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>User Accounts</title> | ||||
|     <title>KTVManager</title> | ||||
|     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> | ||||
|     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css"> | ||||
|     <style> | ||||
| @ -19,7 +19,7 @@ | ||||
| 
 | ||||
|     <!-- Navbar (same as index.html) --> | ||||
|     <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> | ||||
|         <a class="navbar-brand" href="#">KTV Manager</a> | ||||
|         <a class="navbar-brand" href="#">KTVManager</a> | ||||
|         <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> | ||||
|             <span class="navbar-toggler-icon"></span> | ||||
|         </button> | ||||
| @ -40,7 +40,7 @@ | ||||
| 
 | ||||
|     <!-- Main Content --> | ||||
|     <div class="container mt-5"> | ||||
|         <h2>User Accounts</h2> | ||||
|         <h2>{{ username }}'s Accounts</h2> | ||||
|         <table class="table table-striped" id="accountsTable"> | ||||
|             <thead> | ||||
|                 <tr> | ||||
| @ -59,7 +59,7 @@ | ||||
|                     <td>{{ account.username }}</td> | ||||
|                     <td>{{ account.stream }}</td> | ||||
|                     <td><a href="{{ account.streamURL }}" target="_blank">{{ account.streamURL }}</a></td> | ||||
|                     <td>{{ account.expiaryDate }}</td> <!-- Ensure this is in d/m/Y format --> | ||||
|                     <td>{{ account.expiaryDate_rendered }}</td> | ||||
|                     <td class="password-cell" data-password="{{ account.password }}"> | ||||
|                         <span class="password-blur">********</span> | ||||
|                     </td> | ||||
| @ -70,7 +70,7 @@ | ||||
|     </div> | ||||
| 
 | ||||
|     <footer class="bg-dark text-white text-center py-3 mt-5"> | ||||
|         <p>© 2024 My Site | All rights reserved</p> | ||||
|         <p>© 2024 KTVManager | All rights reserved</p> | ||||
|     </footer> | ||||
| 
 | ||||
|     <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Karl Hudgell
						Karl Hudgell