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> |                     <a class="nav-link" href="/">Home</a> | ||||||
|                 </li> |                 </li> | ||||||
|                 <li class="nav-item"> |                 <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> | ||||||
|                 <li class="nav-item"> |                 <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> |                 </li> | ||||||
|             </ul> |             </ul> | ||||||
|         </div> |         </div> | ||||||
| @ -33,7 +33,22 @@ | |||||||
|     <!-- Main Content --> |     <!-- Main Content --> | ||||||
|     <div class="container mt-5"> |     <div class="container mt-5"> | ||||||
|         <h1>Welcome to KTV Manager</h1> |         <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> |     </div> | ||||||
| 
 | 
 | ||||||
|     <footer class="bg-dark text-white text-center py-3 mt-5"> |     <footer class="bg-dark text-white text-center py-3 mt-5"> | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <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"> |     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| @ -53,7 +53,7 @@ | |||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <footer class="bg-dark text-white text-center py-3 mt-5"> |     <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> |     </footer> | ||||||
| 
 | 
 | ||||||
|     <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> |     <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> |     <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://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"> |     <link rel="stylesheet" href="https://cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css"> | ||||||
|     <style> |     <style> | ||||||
| @ -19,7 +19,7 @@ | |||||||
| 
 | 
 | ||||||
|     <!-- Navbar (same as index.html) --> |     <!-- Navbar (same as index.html) --> | ||||||
|     <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> |     <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"> |         <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> |             <span class="navbar-toggler-icon"></span> | ||||||
|         </button> |         </button> | ||||||
| @ -40,7 +40,7 @@ | |||||||
| 
 | 
 | ||||||
|     <!-- Main Content --> |     <!-- Main Content --> | ||||||
|     <div class="container mt-5"> |     <div class="container mt-5"> | ||||||
|         <h2>User Accounts</h2> |         <h2>{{ username }}'s Accounts</h2> | ||||||
|         <table class="table table-striped" id="accountsTable"> |         <table class="table table-striped" id="accountsTable"> | ||||||
|             <thead> |             <thead> | ||||||
|                 <tr> |                 <tr> | ||||||
| @ -59,7 +59,7 @@ | |||||||
|                     <td>{{ account.username }}</td> |                     <td>{{ account.username }}</td> | ||||||
|                     <td>{{ account.stream }}</td> |                     <td>{{ account.stream }}</td> | ||||||
|                     <td><a href="{{ account.streamURL }}" target="_blank">{{ account.streamURL }}</a></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 }}"> |                     <td class="password-cell" data-password="{{ account.password }}"> | ||||||
|                         <span class="password-blur">********</span> |                         <span class="password-blur">********</span> | ||||||
|                     </td> |                     </td> | ||||||
| @ -70,7 +70,7 @@ | |||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <footer class="bg-dark text-white text-center py-3 mt-5"> |     <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> |     </footer> | ||||||
| 
 | 
 | ||||||
|     <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> |     <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