This commit is contained in:
Alex55 2026-03-23 15:12:27 +02:00
parent ad066a84d9
commit f1dd5fb810
14 changed files with 398 additions and 3 deletions

129
API/ggprice.py Normal file
View File

@ -0,0 +1,129 @@
import sqlite3
import requests
import time
# ======================
# CONFIG
# ======================
DB_PATH = "rokky.db"
API_URL = "https://seller.ggsel.com/api_sellers/api/product/edit/prices"
TOKEN = "YOUR_TOKEN"
BATCH_SIZE = 200 # сколько товаров за раз отправлять
SLEEP_BETWEEN = 1 # задержка между батчами (сек)
# ======================
# DB
# ======================
def get_products_for_update(conn):
cursor = conn.cursor()
cursor.execute("""
SELECT product_id, price
FROM products
WHERE product_id IS NOT NULL
AND price IS NOT NULL
""")
return cursor.fetchall()
# ======================
# BUILD PAYLOAD
# ======================
def build_payload(rows):
payload = []
for product_id, price in rows:
payload.append({
"product_id": int(product_id),
"price": float(price)
})
return payload
# ======================
# CHUNKING
# ======================
def chunked(data, size):
for i in range(0, len(data), size):
yield data[i:i + size]
# ======================
# SEND REQUEST
# ======================
def send_prices(payload):
try:
response = requests.post(
f"{API_URL}?token={TOKEN}",
json=payload,
timeout=30
)
print("STATUS:", response.status_code)
if response.status_code != 200:
print("ERROR:", response.text)
return None
data = response.json()
print("RESPONSE:", data)
return data
except Exception as e:
print("REQUEST ERROR:", e)
return None
# ======================
# SYNC
# ======================
def sync_prices():
conn = sqlite3.connect(DB_PATH)
rows = get_products_for_update(conn)
payload = build_payload(rows)
total = len(payload)
print(f"Всего товаров: {total}")
if total == 0:
print("Нет данных для обновления")
return
sent = 0
for batch in chunked(payload, BATCH_SIZE):
print(f"\nОтправка: {sent}{sent + len(batch)}")
result = send_prices(batch)
if result is None:
print("Ошибка при отправке, стоп")
break
sent += len(batch)
time.sleep(SLEEP_BETWEEN)
print(f"\nГотово. Отправлено: {sent}/{total}")
conn.close()
# ======================
# RUN
# ======================
if __name__ == "__main__":
sync_prices()

1
API/ww
View File

@ -0,0 +1 @@
5110eb4a7aa7c60d66f9648db40027f241c52673a6a7c9a136e2a02fd1711fb&amount=1.0&currency=RUB&date=2026-03-20T10=43=09+03=00&email=rusinowdima2@yandex.ru&id_d=102180432&id_i=21327450&ip=188.32.208.151&is_my_product=true

View File

@ -1,4 +1,6 @@
from flask import Blueprint, request, jsonify # from flask import Blueprint, request, jsonify
from flask import Blueprint, request, jsonify, send_from_directory
import os
import sqlite3 import sqlite3
import json import json
# from services.rokky import ones # from services.rokky import ones
@ -11,11 +13,16 @@ import logging
main = Blueprint("main", __name__) main = Blueprint("main", __name__)
DB_PATH = "./files/rokky.db" DB_PATH = "./files/rokky.db"
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
IMAGE_FOLDER = os.path.join(BASE_DIR, 'images')
@main.route("/") @main.route("/")
def index(): def index():
return "Hello wstkeys!!!" return "Hello wstkeys!!!"
@main.route("/images/<filename>")
def get_image(filename):
return send_from_directory(IMAGE_FOLDER, filename)
@main.route("/orders/api_payments", methods=["POST", "GET"]) @main.route("/orders/api_payments", methods=["POST", "GET"])
def index1(): def index1():

BIN
images/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -15,6 +15,9 @@ logging.basicConfig(
app = create_app() app = create_app()
start_scheduler() start_scheduler()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -170,7 +170,7 @@ def get_messages(id_i, id_from=None, id_to=None, newer=None, count=50):
# пример # пример
print(get_messages(id_i=18840912)) # print(get_messages(id_i=18840912))
def get_chats(page=1, pagesize=20, filter_new=None, email=None, id_ds=None): def get_chats(page=1, pagesize=20, filter_new=None, email=None, id_ds=None):
@ -212,6 +212,28 @@ def get_chats(page=1, pagesize=20, filter_new=None, email=None, id_ds=None):
return r.json() return r.json()
def get_product():
token = load_token()
product_id = 102182541
url = f"https://seller.ggsel.com/api_sellers/api/products/{product_id}/data"
params = {
"token": token
}
headers = {
"Accept": "application/json"
}
r = requests.get(url, headers=headers, params=params)
print(r.status_code)
return r.json()
print(get_product())
# пример # пример
# print(get_chats()) # print(get_chats())
# def tokens(): # def tokens():

55
services/mailer.py Normal file
View File

@ -0,0 +1,55 @@
import os
import smtplib
from email.message import EmailMessage
from dotenv import load_dotenv
from utils import build_items_html, build_keys_html, render_template
load_dotenv()
EMAIL_ADDRESS = os.getenv("EMAIL_ADDRESS")
EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")
def send_plain_email(to_address: str, subject: str, body: str):
msg = EmailMessage()
msg['Subject'] = subject
msg['From'] = EMAIL_ADDRESS
msg['To'] = to_address
msg.set_content(body)
with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
smtp.starttls()
smtp.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
smtp.send_message(msg)
print(f"Plain email sent to {to_address}")
def send_html_email(to_address: str, data: dict):
msg = EmailMessage()
msg['Subject'] = f"Order #{data['order_id']}"
msg['From'] = EMAIL_ADDRESS
msg['To'] = to_address
with open('templates/welcome.html', 'r', encoding='utf-8') as f:
html_template = f.read()
html_template = html_template.replace(
"{{items}}", build_items_html(data["items"])
)
html_template = html_template.replace(
"{{keys_block}}", build_keys_html(data.get("keys"))
)
html_content = render_template(html_template, data)
msg.add_alternative(html_content, subtype='html')
with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
smtp.starttls()
smtp.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
smtp.send_message(msg)
print(f"HTML email sent to {to_address}")

66
services/send_mai.py Normal file
View File

@ -0,0 +1,66 @@
import sys
from mailer import send_plain_email, send_html_email
def read_multiline(prompt: str) -> str:
print(prompt)
print("(finish with ';')")
lines = []
while True:
line = input()
if line == ';':
break
lines.append(line)
return '\n'.join(lines)
def send_text_flow():
to_addr = input("Receiver email: ").strip()
subject = input("Subject: ").strip() or "(No subject)"
body = read_multiline("Message:")
send_plain_email(to_addr, subject, body)
def send_html_flow():
to_addr = input("Receiver email: ").strip()
data = {
"company_name": "wstkeys",
"order_id": "123",
"customer_name": "4321",
"currency": "USD",
"items": [
{"name": "Game 1333", "quantity": 1, "price": 1330},
],
"date": "23.03.2026 14:02",
"product_name": "Railroads Online - Pioneer DLC",
"product_image": "https://s3.ggsel.com/gsellers-imgs-prod/e05c8d1f28e18f56334bf8e7e9f7b547.jpeg",
"total_price": 20,
"key": 'XXXX-XXXX-YYY23',
"support_email": "wstkeys@gmail.com",
"year": 2026
}
send_html_email(to_addr, data)
def main():
print("1 - Send plain email")
print("2 - Send HTML email")
choice = input("Choose: ").strip()
if choice == "1":
send_text_flow()
elif choice == "2":
send_html_flow()
else:
print("Invalid choice")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,28 @@
def build_items_html(items):
rows = ""
for item in items:
rows += f"""
<tr>
<td>{item['name']}</td>
<td>{item['quantity']}</td>
<td>{item['price']}</td>
</tr>
"""
return rows
def build_keys_html(keys):
if not keys:
return ""
rows = "<h3>Your Keys:</h3><ul>"
for key in keys:
rows += f"<li style='font-family:monospace'>{key}</li>"
rows += "</ul>"
return rows
def render_template(template_str, data):
for key, value in data.items():
template_str = template_str.replace(f"{{{{{key}}}}}", str(value))
return template_str

View File

@ -8,5 +8,7 @@ def start_scheduler():
# каждые 10 секунд # каждые 10 секунд
scheduler.add_job(run_task, 'interval', minutes=10) scheduler.add_job(run_task, 'interval', minutes=10)
# Раз в сутки (24 часа)
scheduler.add_job(run_task, 'interval', days=1)
scheduler.start() scheduler.start()

28
services/utils.py Normal file
View File

@ -0,0 +1,28 @@
def build_items_html(items):
rows = ""
for item in items:
rows += f"""
<tr>
<td>{item['name']}</td>
<td>{item['quantity']}</td>
<td>{item['price']}</td>
</tr>
"""
return rows
def build_keys_html(keys):
if not keys:
return ""
rows = "<h3>Keys:</h3><ul>"
for key in keys:
rows += f"<li style='font-family:monospace'>{key}</li>"
rows += "</ul>"
return rows
def render_template(template_str, data):
for key, value in data.items():
template_str = template_str.replace(f"{{{{{key}}}}}", str(value))
return template_str

54
templates/welcome.html Normal file
View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<body style="font-family: Arial, sans-serif; background:#0f0f0f; padding:20px; color:#fff;">
<table width="600" align="center" style="background:#111; padding:20px; border:1px solid #00cfff;">
<tr>
<td align="center">
<!-- LOGO -->
<div style="text-align:center; margin-bottom:10px;">
<img src="{{ url_for('main.get_image', filename='1.jpg') }}" alt="logo"
style="max-width:200px; height:auto;">
</div>
<!--<h1 style="color:#00cfff; margin-bottom:5px;">{{company_name}}</h1>-->
<p style="margin:0; color:#aaa; font-size:16px;">Спасибо за покупку в WST Keys (West Store Trusted Keys)</p>
<hr style="border:1px solid #00cfff; margin:20px 0;">
<!-- ORDER INFO -->
<p style="font-size:16px;"><b> Дата покупки: </b> {{date}}</p>
<p style="font-size:16px;"><b> Номер заказа: </b> {{order_id}}</p>
<h3 style="margin-top:20px; font-size:22px;">{{product_name}}</h3>
<img src="{{product_image}}" width="100%" style="max-width:400px; margin:10px 0; border:1px solid #00cfff;">
<p style="font-size:16px;"><b>Сумма:</b> {{total_price}} {{currency}}</p>
<hr style="border:1px solid #00cfff; margin:20px 0;">
<!-- KEYS -->
<h3 style="color:#00ff9d;"> Цифровой ключ</h3>
<div style="background:#000; padding:10px; border:1px dashed #00ff9d; margin:10px 0;">
<code style="color:#00ff9d; font-size:16px;">{{key}}</code>
</div>
<hr style="border:1px solid #00cfff; margin:20px 0;">
<!-- INFO -->
<p style="color:#ccc;">
</p>
<p style="margin-top:20px;">
Если у вас возникнут вопросы, напишите в личные сообщения или свяжитесь с нами по электронной почте <br> <a href="mailto:{{support_email}}" style="color:#00cfff;">{{support_email}}</a>
</p>
</td>
</tr>
</table>
</body>
</html>