Compare commits

...

15 Commits

13 changed files with 156 additions and 62 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
__pycacahe__/*
freeriders/__pycacahe__/*
instance/

View File

@ -1,3 +1,10 @@
# freeriders
Web app for tracking current ticket numbers
Web app for tracking current ticket numbers
# Architecture
- keep all ticket numbers and timestamps in SQL table "tickets"
- display last ticket number
- don't allow tickets that are out of probable ticket number range
- if last submited ticket is timestamped more then 90 minutes ago, try to predict the next number

View File

@ -4,7 +4,7 @@ Priority: optional
Architecture: all
Essential: no
Installed-Size: 2000
Depends: python3-flask, gunicorn
Depends: gunicorn, python3-flask-sqlalchemy
Homepage: https://gitea.dmz.rs/Decentrala/freeriders
Maintainer: Decentrala <dmz@dmz.rs>
Description: Web app that tracks bus transport ticket numbers

View File

@ -1,5 +1,16 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os # if you wanna have db credenitalas in os.environ
app = Flask(__name__)
# SQLAlchemy setup
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///freeriders.db'
#MySql setup
#app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://user:pass@localhost/dbname'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
from freeriders import routes

21
freeriders/functions.py Normal file
View File

@ -0,0 +1,21 @@
import time
import datetime
def datetounix(day, month, year, hour, minute, second):
seconds = datetime.datetime(year, month, day, hour, minute, second).timestamp()
return int(seconds)
def formatprefix2(number):
return "{:02d}".format(number)
def formatprefix10(number):
return "{:010d}".format(number)
def predict(timestamp):
base_ticket = 7157662
base_timestamp = 1695887564
step = 0.688
ticket = base_ticket + (timestamp - base_timestamp) * step
return int(ticket)

6
freeriders/models.py Normal file
View File

@ -0,0 +1,6 @@
from freeriders import db
class Tickets(db.Model):
id = db.Column(db.Integer, primary_key=True)
ticket = db.Column(db.Integer, nullable=False)
timestamp = db.Column(db.Integer, nullable=False)

View File

@ -1,10 +1,58 @@
from flask import render_template, request, redirect
from freeriders import app
from freeriders import app, db
from freeriders.functions import formatprefix2,formatprefix10, predict
from freeriders.models import Tickets
from datetime import datetime
import time
@app.route('/', methods=['POST', 'GET'])
def changepassword():
@app.route('/sms', methods=['GET'])
def sms():
if request.method == 'GET':
return render_template('index.html')
elif request.method == 'POST':
timenow = int(time.time())
try:
lastticket = Tickets.query.order_by(Tickets.timestamp.desc()).first()
if lastticket.timestamp < timenow - (90 * 60):
lastticket = formatprefix10(predict(timenow))
else:
lastticket = formatprefix10(lastticket.ticket)
date = datetime.now()
datenow = f'{formatprefix2(date.day)}.{formatprefix2(date.month)}.{date.year}'
timenow = f'{formatprefix2(date.hour)}:{formatprefix2(date.minute)}:{formatprefix2(date.second)}'
return render_template('sms.html', ticket = lastticket, date = datenow, time = timenow)
except:
return 'Error retriving last ticket'
else:
return 'HTTP request method not recogniezed'
@app.route('/submit', methods=['POST', 'GET'])
def submit():
PREDICTTIMERANGE = 60 * 60 * 24
if request.method == 'GET':
return render_template('submit.html')
elif request.method == 'POST':
timenow = int(time.time())
ticket_input = request.form['ticket']
if ticket_input.isdigit() and len(ticket_input) == 10 :
if int(ticket_input) < predict(timenow + PREDICTTIMERANGE ) and int(ticket_input) > predict(timenow - PREDICTTIMERANGE ) :
ticket = Tickets(ticket = int(ticket_input), timestamp = timenow)
else:
print(int(ticket_input))
print(predict(timenow - PREDICTTIMERANGE))
print(predict(timenow + PREDICTTIMERANGE))
print(predict(timenow))
return 'Ticket number is in unexpected range.'
else:
return 'Ticket format is wrong. Only 10 digits allowed.'
try:
db.session.add(ticket)
db.session.commit()
return 'Ticket added'
except:
return 'Adding ticket failed'
else:
return 'HTTP request method not recogniezed'

View File

@ -1,9 +1,9 @@
:root {
--border-radus: 1rem;
--background: #EEE;
--header-background: #DDD;
--background: #F9F9F9;
--header-background: #EEE;
--header-height: 3rem;
--input-bar-height: 2rem;
--input-bar-height: 3rem;
}
body{
@ -14,14 +14,13 @@ body{
}
main {
max-width: 400px;
display: flex;
flex-direction: column;
align-self: flex-start;
gap: 1rem;
margin: 0 auto;
padding: 1rem 0.5rem;
height: calc(100vh - 5rem);
padding: 2rem 0.5rem;
height: calc(100vh - var(--header-height) - var(--input-bar-height));
overflow-y: scroll;
box-sizing: border-box;
}
@ -30,22 +29,25 @@ header {
background-color: var(--header-background);
display: flex;
flex-direction: row;
padding: 1rem;
align-items: center;
padding: 0 1rem;
gap: 1rem;
font-weight: bold;
width: 100vw;
height: var(header-height);
height: var(--header-height);
box-sizing: border-box;
}
footer {
width: 100vw;
height: var(input-bar-height);
background-color: #FDD;
height: var(--input-bar-height);
background-color: var(--background);
display: flex;
flex-direction: row;
align-items: center;
padding: 0 1rem;
box-sizing: border-box;
gap: 1rem;
}
.request {
@ -67,4 +69,12 @@ footer {
.date {
align-self: center;
margin-top: 0.5rem;
}
.textbox{
background-color: var(--header-background);
width: 80%;
height: 1rem;
padding: 0.2rem;
border-radius: 2rem;
}

View File

@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/styles/style.css">
<link rel="shortcut icon" href="/img/favicon.ico" type="image/x-icon">
<title>Ticket tracking</title>
</head>
<body>
<main>
</main>
</body>
</html>

View File

@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Karta</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<header>
@ -20,35 +20,8 @@
U Beogradu, za broj telefona ste kupili
VREMENSKU KARTU OD 90 MINUTA U ZONI A po
ceni od 50 din + osnovna cena poruke,
koja vazi do 03.10.2023, 09:42:54.
Karta broj: 0000343232.
Placanjem operateru izmirujete dugovanja
za ovu kartu prema JKP Naplata prevozne
usluge Beograd. Sacuvajte ovu poruku.
</section>
<section class='request'>
A90
</section>
<section class='ticket'>
U Beogradu, za broj telefona ste kupili
VREMENSKU KARTU OD 90 MINUTA U ZONI A po
ceni od 50 din + osnovna cena poruke,
koja vazi do 03.10.2023, 09:42:54.
Karta broj: 0000343232.
Placanjem operateru izmirujete dugovanja
za ovu kartu prema JKP Naplata prevozne
usluge Beograd. Sacuvajte ovu poruku.
</section>
<section class='date'>08:23</section>
<section class='request'>
A90
</section>
<section class='ticket'>
U Beogradu, za broj telefona ste kupili
VREMENSKU KARTU OD 90 MINUTA U ZONI A po
ceni od 50 din + osnovna cena poruke,
koja vazi do 03.10.2023, 09:42:54.
Karta broj: 0000343232.
koja vazi do {{ date }}, {{ time }}.
Karta broj: {{ ticket }}.
Placanjem operateru izmirujete dugovanja
za ovu kartu prema JKP Naplata prevozne
usluge Beograd. Sacuvajte ovu poruku.
@ -59,4 +32,4 @@
<div>x</div>
</footer>
</body>
</html>
</html>

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Submit</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>
<main>
<form action="/submit" method="POST">
<label for="ticket">ticket</label>
<input type="text" name="ticket" id="ticket" placeholder="1234567890" required>
<button> Submit </button>
</form>
</main>
</body>
</html>

10
init_db.py Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env python3
from freeriders import db
print('[i] Trying to create databse...')
try:
db.create_all()
print('[+] Success you can proceed with deployment!')
except:
print('[-] Creating db failed :/')

View File

@ -1 +1,2 @@
flask
SQLAlchemy