Автор не я взял с Англ сайта
Эта система использует скрипт attendance.py для регистрации времени онлайн. Она не идеальна, так как её можно обойти, но чтобы подключить базу данных к запросу на вход в игру, нужны знания и инструменты. Так что да, система несовершенна, но её можно использовать.
Эта система использует скрипт attendance.py для регистрации времени онлайн. Она не идеальна, так как её можно обойти, но чтобы подключить базу данных к запросу на вход в игру, нужны знания и инструменты. Так что да, система несовершенна, но её можно использовать.
Код:
'''
Attendance Reward System with Cooldown Timer + Auto Heartbeat
- On login: registers user as "online"
- On logout: unregisters user
- Auto heartbeat: keeps user online as long as page is open
- Auto-reward script uses this to find active users
'''
import os
from datetime import datetime, timedelta, date
import pyodbc
from flask import (
Flask, request, redirect, url_for, session,
render_template_string, flash
)
app = Flask(__name__)
app.secret_key = os.environ.get("FLASK_SECRET", "dev-secret-attendance-v4")
app.permanent_session_lifetime = timedelta(hours=2)
# --- DB config ---
SQL_SERVER = os.environ.get("SQL_SERVER", "YOURDB\\HERE")
USE_SQL_AUTH = os.environ.get("USE_SQL_AUTH", "0") == "1"
SQL_USER = os.environ.get("SQL_USER", "")
SQL_PASS = os.environ.get("SQL_PASS", "")
WORLD_DB = "SA_BETA_WORLDDB_0002"
TRADE_DB = "SA_BETA_TRADEDB_0002"
# --- Reward Configuration (ITEMS ONLY) ---
REWARDS = {
1: [(16080, 5, 0)], # Cron Stone x5
2: [(17809, 1, 0)], # Advice of Valks 10
3: [(16080, 10, 0)], # Cron Stone x10
4: [(17819, 1, 0)], # Advice of Valks 20
5: [(757008, 1, 0)], # Mythical Censer
6: [(17829, 1, 0)], # Advice of Valks 30
7: [(45077, 3, 0)], # J's Hammer of Loyalty
8: [(17839, 1, 0)], # Advice of Valks 40
9: [(16080, 15, 0)], # Cron Stone x15
10: [(17849, 1, 0)], # Advice of Valks 50
11: [(17859, 1, 0)], # Advice of Valks 60
12: [(16080, 20, 0)], # Cron Stone x20
13: [(17869, 1, 0)], # Advice of Valks 70
14: [(17879, 1, 0)], # Advice of Valks 80
15: [(16080, 25, 0)], # Cron Stone x25
16: [(17889, 1, 0)], # Advice of Valks 90
17: [(17899, 1, 0)], # Advice of Valks 100
18: [(16080, 30, 0)], # Cron Stone x30
19: [(757008, 2, 0)], # Mythical Censer x2
20: [(45077, 3, 0)], # J's Hammer of Loyalty
21: [(16080, 40, 0)], # Cron Stone x40
22: [(17899, 2, 0)], # Advice of Valks 100 x2
23: [(16080, 50, 0)], # Cron Stone x50
24: [(757008, 3, 0)], # Mythical Censer x3
25: [(45077, 3, 0)], # J's Hammer of Loyalty
26: [(16080, 60, 0)], # Cron Stone x60
27: [(17899, 3, 0)], # Advice of Valks 100 x3
28: [(16080, 75, 0)], # Cron Stone x75
29: [(757008, 5, 0)], # Mythical Censer x5
30: [(45077, 3, 0)], # J's Hammer of Loyalty
}
# Preload item names for UI
ITEM_NAMES = {
16080: "Cron Stone",
17809: "Advice of Valks 10",
17819: "Advice of Valks 20",
17829: "Advice of Valks 30",
17839: "Advice of Valks 40",
17849: "Advice of Valks 50",
17859: "Advice of Valks 60",
17869: "Advice of Valks 70",
17879: "Advice of Valks 80",
17889: "Advice of Valks 90",
17899: "Advice of Valks 100",
757008: "Mythical Censer",
45077: "J's Hammer of Loyalty",
}
def get_conn(database_name: str):
"""Create an ODBC connection to the specified database."""
driver = "{ODBC Driver 17 for SQL Server}"
if USE_SQL_AUTH:
cs = (
f"DRIVER={driver};SERVER={SQL_SERVER};DATABASE={database_name};"
f"UID={SQL_USER};PWD={SQL_PASS};TrustServerCertificate=yes;"
)
else:
cs = (
f"DRIVER={driver};SERVER={SQL_SERVER};DATABASE={database_name};"
f"Trusted_Connection=yes;TrustServerCertificate=yes;"
)
return pyodbc.connect(cs)
# --- Ensure ActiveSessions Table Exists ---
def ensure_active_sessions_table():
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'ActiveSessions')
EXEC('CREATE SCHEMA ActiveSessions');
""")
cur.execute("""
IF NOT EXISTS (
SELECT * FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE s.name = 'ActiveSessions' AND t.name = 'TblActiveConnections'
)
BEGIN
CREATE TABLE ActiveSessions.TblActiveConnections (
_userNo INT NOT NULL PRIMARY KEY,
_nickname NVARCHAR(50) NOT NULL,
_loginTime DATETIME2(3) NOT NULL DEFAULT SYSUTCDATETIME(),
_lastHeartbeat DATETIME2(3) NOT NULL DEFAULT SYSUTCDATETIME(),
_ipAddress VARCHAR(45) NULL
);
CREATE INDEX IX_Heartbeat ON ActiveSessions.TblActiveConnections (_lastHeartbeat);
END
""")
except Exception as e:
print(f"[DB] Failed to create ActiveSessions table: {e}")
# --- Register Active Session ---
def register_active_session(user_no: int, nickname: str, ip: str = None):
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
MERGE ActiveSessions.TblActiveConnections AS target
USING (SELECT ? AS _userNo, ? AS _nickname, ? AS _ipAddress) AS source
ON target._userNo = source._userNo
WHEN MATCHED THEN
UPDATE SET
_nickname = source._nickname,
_lastHeartbeat = SYSUTCDATETIME(),
_ipAddress = source._ipAddress
WHEN NOT MATCHED THEN
INSERT (_userNo, _nickname, _ipAddress)
VALUES (source._userNo, source._nickname, source._ipAddress);
""", (user_no, nickname, ip))
except Exception as e:
print(f"[Session] Failed to register active session: {e}")
# --- Unregister Active Session ---
def unregister_active_session(user_no: int):
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
DELETE FROM ActiveSessions.TblActiveConnections
WHERE _userNo = ?
""", (user_no,))
except Exception as e:
print(f"[Session] Failed to unregister session: {e}")
def send_mail(nickname: str, item_id: int, qty: int, enchant: int = 0) -> str:
"""Send item via mail using sendMail stored procedure. Returns symNo or 'UNKNOWN' if not returned."""
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
DECLARE @symNo NVARCHAR(50);
EXEC SA_BETA_WORLDDB_0002.dbo.sendMail
@toFamilyName = ?,
@itemKey = ?,
@itemCount = ?,
@enchant = ?,
@title = N'Daily Attendance Reward',
@contents = N'Thank you for logging in daily!',
@symNo = @symNo OUTPUT;
SELECT @symNo AS symNo;
""", (nickname, item_id, qty, enchant))
row = cur.fetchone()
if row:
return row[0] if row[0] else "UNKNOWN"
else:
return "UNKNOWN"
except Exception as e:
print(f"[Mail Error] {e}")
return ""
def record_attendance(user_no: int) -> tuple[int, bool]:
today = date.today()
try:
with get_conn(WORLD_DB) as conn:
conn.autocommit = False
cur = conn.cursor()
cur.execute("""
SELECT _lastAttendanceDate, _attendanceCount
FROM PaGamePrivate.TblUserAttendance WITH (UPDLOCK, ROWLOCK)
WHERE _userNo = ?
""", (user_no,))
row = cur.fetchone()
if row:
last_date = row[0].date() if row[0] else None
count = int(row[1])
if last_date == today:
conn.rollback()
return count, False
if last_date == today - timedelta(days=1):
new_count = count + 1
else:
new_count = 1
cur.execute("""
UPDATE PaGamePrivate.TblUserAttendance
SET _lastAttendanceDate = ?, _attendanceCount = ?
WHERE _userNo = ?
""", (today, new_count, user_no))
else:
new_count = 1
cur.execute("""
INSERT INTO PaGamePrivate.TblUserAttendance (_userNo, _lastAttendanceDate, _attendanceCount)
VALUES (?, ?, ?)
""", (user_no, today, new_count))
conn.commit()
return new_count, True
except Exception:
return 0, False
# ---------- HTML Templates ----------
LOGIN_HTML = """<!doctype html>
<html><head>
<meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Attendance Reward – Sign in</title>
<style>
body{margin:0;font-family:system-ui,Segoe UI,Arial;background:#0b0d11;color:#e6e6e6;display:grid;place-items:center;height:100vh}
.card{background:#141922;border:1px solid #232a36;border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.35);padding:28px;min-width:300px;max-width:360px}
h1{margin:0 0 6px 0;font-size:22px}
p.sub{margin:0 0 16px 0;color:#aab3c2;font-size:13px}
label{display:block;margin:12px 0 6px 0;font-size:13px;color:#aab3c2}
input{width:100%;padding:10px 12px;border:1px solid #2a3140;background:#0f131a;color:#e6e6e6;border-radius:10px}
button{margin-top:16px;width:100%;padding:10px 12px;border:0;border-radius:10px;background:#3b82f6;color:white;font-weight:600;cursor:pointer}
.err{margin-top:10px;color:#ff7070;font-size:13px}
.msg{margin-top:10px;color:#87d17e;font-size:13px}
</style>
</head>
<body>
<form class="card" method="post" action="/">
<h1>Daily Attendance</h1>
<p class="sub">Sign in to claim your daily reward</p>
<label>Username</label>
<input name="username" autocomplete="username" required />
<label>Password</label>
<input name="password" type="password" autocomplete="current-password" required />
<button type="submit">Sign in</button>
{% if error %}<div class="err">{{ error }}</div>{% endif %}
{% for m in get_flashed_messages() %}<div class="msg">{{ m }}</div>{% endfor %}
</form>
</body></html>"""
HOME_HTML = """<!doctype html>
<html><head>
<meta charset="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Attendance Reward – Home</title>
<style>
body{background:#0b0d11;color:#e6e6e6;font-family:system-ui,Segoe UI,Arial;margin:0}
header{display:flex;justify-content:space-between;align-items:center;padding:14px 18px;background:#141922;border-bottom:1px solid #232a36}
main{padding:24px}
.meta{color:#aab3c2;font-size:14px;margin:6px 0 18px}
.streak{font-size:20px;margin:16px 0;color:#ffd700}
.cooldown{font-size:16px;margin:8px 0;color:#ffcc00;font-weight:bold}
button{padding:8px 16px;border:0;border-radius:8px;background:#3b82f6;color:#fff;cursor:pointer;font-weight:600}
button:disabled{background:#4a5568;cursor:not-allowed}
.flash-ok{color:#7be18a;margin:6px 0;font-weight:bold}
.flash-err{color:#ff7070;margin:6px 0;font-weight:bold}
.reward-table{width:100%;border-collapse:collapse;margin-top:20px}
.reward-table th, .reward-table td{padding:10px;border-bottom:1px solid #232a36;text-align:left}
.reward-table th{color:#aab3c2;background:#1a202c}
.today-row{background:#1e293b;animation: pulse 2s infinite;}
.claim-btn{margin-top:8px}
@keyframes pulse {
0%{background:#1e293b}
50%{background:#2d3748}
100%{background:#1e293b}
}
</style>
</head>
<body>
<header>
<div><strong>Daily Attendance</strong></div>
<form method="post" action="/logout"><button type="submit">Logout</button></form>
</header>
<main>
<h2>Welcome, {{ username }}</h2>
<div class="streak">🔥 Current Streak: Day {{ streak }} (Reward Day: {{ reward_day }})</div>
{% if cooldown %}
<div class="cooldown">⏳ Next claim in: {{ cooldown }}</div>
{% endif %}
{% for m in get_flashed_messages(category_filter=["ok"]) %}<div class="flash-ok">{{ m }}</div>{% endfor %}
{% for m in get_flashed_messages(category_filter=["err"]) %}<div class="flash-err">{{ m }}</div>{% endfor %}
<h3>Reward Schedule</h3>
<table class="reward-table">
<thead><tr><th>Day</th><th>Items</th><th>Action</th></tr></thead>
<tbody>
{% for day in range(1, 31) %}
<tr {% if day == reward_day %}class="today-row"{% endif %}>
<td>{{ day }}</td>
<td>
{% if day in rewards %}
{% for item_id, qty, enchant in rewards[day] %}
{{ item_names[item_id] }} x{{ qty }}
{% if not loop.last %}, {% endif %}
{% endfor %}
{% else %}
—
{% endif %}
</td>
<td>
{% if day == reward_day and can_claim %}
<form method="post" action="/claim" class="claim-btn">
<button type="submit">🎁 Claim Now</button>
</form>
{% elif day == reward_day and not can_claim %}
<button disabled>✅ Claimed Today</button>
{% else %}
<button disabled>🔒 Future Reward</button>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</main>
<!-- ✅ AUTO HEARTBEAT: Keeps user "online" as long as this tab is open -->
<script>
async function sendHeartbeat() {
try {
await fetch('/heartbeat', { method: 'POST' });
} catch (e) {
console.log('Heartbeat failed:', e);
}
}
// Send heartbeat every 10 seconds
setInterval(sendHeartbeat, 10000);
// Send one immediately on page load
sendHeartbeat();
</script>
</body></html>"""
# -------------------- Routes --------------------
@app.route("/", methods=["GET", "POST"])
def login():
error = None
if request.method == "POST":
username = request.form.get("username", "").strip()
password = request.form.get("password", "")
if not username or not password:
error = "Enter both fields."
else:
user_id = f"{username},{password}"
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
SELECT TOP 1 _userNo, _userNickname
FROM PaGamePrivate.TblUserInformation WITH (NOLOCK)
WHERE _userId = ?
""", (user_id,))
row = cur.fetchone()
if row:
session.permanent = True
session["username"] = username
session["_userNo"] = int(row[0])
session["_nickname"] = row[1] or username
# ✅ Register as online
ensure_active_sessions_table()
register_active_session(session["_userNo"], session["_nickname"], request.remote_addr)
return redirect(url_for("home"))
else:
error = "Invalid credentials."
except Exception as ex:
error = f"DB error: {ex}"
return render_template_string(LOGIN_HTML, error=error)
@app.route("/home")
def home():
if "username" not in session:
return redirect(url_for("login"))
user_no = session["_userNo"]
streak = 0
can_claim = False
last_claim_date = None
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
SELECT _lastAttendanceDate, _attendanceCount
FROM PaGamePrivate.TblUserAttendance WITH (NOLOCK)
WHERE _userNo = ?
""", (user_no,))
row = cur.fetchone()
if row:
last_claim_date = row[0].date() if row[0] else None
streak = int(row[1])
can_claim = (last_claim_date != date.today())
else:
streak = 0
can_claim = True
except Exception:
streak = 0
can_claim = False
reward_day = ((streak - 1) % 30) + 1 if streak > 0 else 1
cooldown = ""
if not can_claim and last_claim_date == date.today():
now = datetime.now()
tomorrow = datetime.combine(date.today() + timedelta(days=1), datetime.min.time())
remaining = tomorrow - now
hours, remainder = divmod(remaining.seconds, 3600)
minutes, _ = divmod(remainder, 60)
if remaining.days > 0:
cooldown = f"{remaining.days} days"
else:
cooldown = f"{hours}h {minutes}m"
return render_template_string(
HOME_HTML,
username=session["username"],
streak=streak,
reward_day=reward_day,
can_claim=can_claim,
cooldown=cooldown,
rewards=REWARDS,
item_names=ITEM_NAMES,
range=range
)
@app.route("/logout", methods=["POST"])
def logout():
# ✅ Unregister as online
if "_userNo" in session:
unregister_active_session(session["_userNo"])
session.clear()
flash("Signed out.", "ok")
return redirect(url_for("login"))
@app.route("/claim", methods=["POST"])
def claim():
if "username" not in session:
return redirect(url_for("login"))
user_no = session["_userNo"]
nickname = session.get("_nickname", session["username"])
streak, is_first_claim = record_attendance(user_no)
if not is_first_claim:
flash("You already claimed today's reward.", "err")
return redirect(url_for("home"))
reward_day = ((streak - 1) % 30) + 1
reward_items = REWARDS.get(reward_day, [])
if not reward_items:
flash("No reward configured for today.", "err")
return redirect(url_for("home"))
messages = []
any_failed = False
for item_id, qty, enchant in reward_items:
sym_no = send_mail(nickname, item_id, qty, enchant)
item_name = ITEM_NAMES.get(item_id, f"Item {item_id}")
if sym_no is not None:
messages.append(f"📬 {item_name} x{qty} sent to your mailbox!")
else:
any_failed = True
messages.append(f"❌ Failed to send {item_name} x{qty}")
if not any_failed:
flash(f"🎉 Day {streak} Reward Claimed! " + " | ".join(messages), "ok")
else:
flash("⚠️ Partial failure: " + " | ".join(messages), "err")
return redirect(url_for("home"))
# --- NEW: Heartbeat Route ---
@app.route("/heartbeat", methods=["POST"])
def heartbeat():
"""Update user's last heartbeat timestamp."""
if "_userNo" not in session:
return "", 401
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
UPDATE ActiveSessions.TblActiveConnections
SET _lastHeartbeat = SYSUTCDATETIME()
WHERE _userNo = ?
""", (session["_userNo"],))
return "", 204 # No content, success
except Exception as e:
print(f"[Heartbeat] Error: {e}")
return "", 500
if __name__ == "__main__":
from waitress import serve
print("🚀 Serving Attendance System at http://0.0.0.0:8893")
serve(app, host="0.0.0.0", port=8893)
Код:
'''
Automatic Ordered Reward Service
- Runs every 30 minutes
- Rewards all users with active heartbeat (last 15 mins)
- Uses ordered reward cycle (1-20)
'''
import os
import pyodbc
import time
import logging
# --- Configuration (MUST MATCH YOUR FLASK APP) ---
SQL_SERVER = os.environ.get("SQL_SERVER", "YOURDB\\HERE")
USE_SQL_AUTH = os.environ.get("USE_SQL_AUTH", "0") == "1"
SQL_USER = os.environ.get("SQL_USER", "")
SQL_PASS = os.environ.get("SQL_PASS", "")
WORLD_DB = "SA_BETA_WORLDDB_0002"
# --- Ordered Reward Pool (20 items) ---
ORDERED_REWARDS = [
(757360, 3), # Cycle 1: Greeat Pioneer Chest
(757360, 3), # Cycle 2: Cron Stone x3
(757360, 3), # Cycle 3: Cron Stone x5
(757360, 3), # Cycle 4: Advice of Valks 10
(757360, 3), # Cycle 5: Advice of Valks 20
(757360, 3), # Cycle 6: Advice of Valks 30
(757360, 3), # Cycle 7: Advice of Valks 40
(757360, 3), # Cycle 8: Advice of Valks 50
(757360, 3), # Cycle 9: Advice of Valks 100
(757360, 3), # Cycle 10: Mythical Censer
(757360, 3), # Cycle 11: J's Hammer of Loyalty
(757360, 3), # Cycle 12: [Event] Shakatu's Luxury Box II
(757360, 3), # Cycle 13: [Event] Shakatu's Shiny Box(Life)
(757360, 3), # Cycle 14: [Event] Shakatu's Shiny Box(Combat)
(757360, 3), # Cycle 15: [Pet]Hedgehog
(757360, 3), # Cycle 16: Flower of Oblivion
(757360, 3), # Cycle 17: Royal Fern Root
(757360, 3), # Cycle 18: Mythical Feather
(757360, 3), # Cycle 19: Fruit of Yianaros
(757360, 3), # Cycle 20: Rainbow Gem Fruit
]
COUNTER_FILE = "reward_cycle_counter.txt"
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s | %(levelname)s | %(message)s',
handlers=[logging.FileHandler("auto_reward.log", encoding='utf-8'), logging.StreamHandler()]
)
logger = logging.getLogger()
def get_conn(database_name: str):
driver = "{ODBC Driver 17 for SQL Server}"
if USE_SQL_AUTH:
cs = f"DRIVER={driver};SERVER={SQL_SERVER};DATABASE={database_name};UID={SQL_USER};PWD={SQL_PASS};TrustServerCertificate=yes;"
else:
cs = f"DRIVER={driver};SERVER={SQL_SERVER};DATABASE={database_name};Trusted_Connection=yes;TrustServerCertificate=yes;"
return pyodbc.connect(cs)
def send_mail(nickname: str, item_id: int, qty: int, enchant: int = 0) -> bool:
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
DECLARE @symNo NVARCHAR(50);
EXEC SA_BETA_WORLDDB_0002.dbo.sendMail
@toFamilyName = ?,
@itemKey = ?,
@itemCount = ?,
@enchant = ?,
@title = N'30-Minute Ordered Reward',
@contents = N'Thank you for playing! Here is your scheduled reward.',
@symNo = @symNo OUTPUT;
SELECT @symNo AS symNo;
""", (nickname, item_id, qty, enchant))
return True
except Exception as e:
logger.error(f"Mail send failed for {nickname}: {e}")
return False
def get_active_users():
"""Get users with heartbeat in last 15 minutes"""
users = []
try:
with get_conn(WORLD_DB) as conn, conn.cursor() as cur:
cur.execute("""
SELECT _nickname
FROM ActiveSessions.TblActiveConnections
WHERE _lastHeartbeat >= DATEADD(MINUTE, -15, SYSUTCDATETIME())
AND _nickname IS NOT NULL
AND _nickname != ''
""")
users = [row[0] for row in cur.fetchall()]
logger.info(f"Found {len(users)} active users (via Flask login)")
except Exception as e:
logger.error(f"Error fetching active users: {e}")
return users
def get_next_reward_cycle():
try:
if os.path.exists(COUNTER_FILE):
with open(COUNTER_FILE, "r") as f:
cycle = int(f.read().strip())
else:
cycle = 0
next_cycle = cycle % len(ORDERED_REWARDS) + 1
with open(COUNTER_FILE, "w") as f:
f.write(str(next_cycle))
return next_cycle
except Exception as e:
logger.error(f"Error managing cycle counter: {e}. Defaulting to cycle 1.")
return 1
def distribute_rewards():
logger.info("Starting 30-minute ordered reward cycle...")
cycle_number = get_next_reward_cycle()
item_id, qty = ORDERED_REWARDS[cycle_number - 1]
logger.info(f"Current reward cycle: #{cycle_number} -> Item {item_id} x{qty}")
users = get_active_users()
if not users:
logger.info("No active users found.")
return
success = 0
for nickname in users:
if send_mail(nickname, item_id, qty):
logger.info(f" -> Sent to {nickname}")
success += 1
else:
logger.warning(f" -> Failed for {nickname}")
logger.info(f"Cycle #{cycle_number} complete: {success}/{len(users)} rewards sent.")
def main():
logger.info("🚀 Ordered Auto Reward Service Started")
logger.info("Will run every 30 minutes. Press Ctrl+C to stop.")
while True:
try:
distribute_rewards()
logger.info("Sleeping for 30 minutes...\n")
time.sleep(1800) # 30 minutes
except KeyboardInterrupt:
logger.info("🛑 Service stopped by user.")
break
except Exception as e:
logger.error(f"💥 Unexpected error: {e}")
time.sleep(60)
if __name__ == "__main__":
main()