231312
This commit is contained in:
parent
ad066a84d9
commit
f1dd5fb810
|
|
@ -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
1
API/ww
|
|
@ -0,0 +1 @@
|
|||
5110eb4a7aa7c60d66f9648db40027f241c52673a6a7c9a136e2a02fd1711fb&amount=1.0¤cy=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
|
||||
Binary file not shown.
|
|
@ -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 json
|
||||
# from services.rokky import ones
|
||||
|
|
@ -11,11 +13,16 @@ import logging
|
|||
main = Blueprint("main", __name__)
|
||||
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("/")
|
||||
def index():
|
||||
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"])
|
||||
def index1():
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
3
main.py
3
main.py
|
|
@ -15,6 +15,9 @@ logging.basicConfig(
|
|||
|
||||
|
||||
app = create_app()
|
||||
|
||||
|
||||
|
||||
start_scheduler()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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):
|
||||
|
|
@ -212,6 +212,28 @@ def get_chats(page=1, pagesize=20, filter_new=None, email=None, id_ds=None):
|
|||
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())
|
||||
# def tokens():
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -8,5 +8,7 @@ def start_scheduler():
|
|||
|
||||
# каждые 10 секунд
|
||||
scheduler.add_job(run_task, 'interval', minutes=10)
|
||||
# Раз в сутки (24 часа)
|
||||
scheduler.add_job(run_task, 'interval', days=1)
|
||||
|
||||
scheduler.start()
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
Loading…
Reference in New Issue