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