Pending barcodes (Networked)

Collects barcodes with the reliability of v2.2.0 and syncs them via a local server.

这些是此脚本的所有版本。 只显示代码变更过的版本。

  • v3.5.1 2025-10-16

    import json
    import socket
    import threading
    import time
    from flask import Flask, request, jsonify
    from flask_cors import CORS
    import os

    # --- Configuration ---
    BARCODES_FILE = 'barcodes.json'
    SERVER_PORT = 5678 # Port for the web server (for Tampermonkey)
    BROADCAST_PORT = 5679 # Port for network discovery and sync
    BROADCAST_INTERVAL = 20 # Seconds between sync broadcasts

    # --- Flask Web Server Setup ---
    app = Flask(__name__)
    CORS(app) # Allow requests from the Tampermonkey script

    # --- Barcode Data Management ---
    data_lock = threading.Lock()

    def load_barcodes():
    """Safely loads barcodes from the JSON file."""
    with data_lock:
    if not os.path.exists(BARCODES_FILE):
    return []
    try:
    with open(BARCODES_FILE, 'r') as f:
    return json.load(f)
    except (json.JSONDecodeError, IOError):
    return []

    def save_barcodes(barcodes):
    """Safely saves barcodes to the JSON file."""
    with data_lock:
    # Sort by count to maintain some order
    barcodes.sort(key=lambda x: x.get('count', 0))
    with open(BARCODES_FILE, 'w') as f:
    json.dump(barcodes, f, indent=4)

    def merge_barcodes(local_list, received_list):
    """Merges two lists of barcodes, avoiding duplicates based on the 'barcode' value."""
    merged_dict = {item['barcode']: item for item in local_list}
    changed = False
    for item in received_list:
    if item['barcode'] not in merged_dict:
    merged_dict[item['barcode']] = item
    changed = True
    else:
    if item.get('found', False) and not merged_dict[item['barcode']].get('found', False):
    merged_dict[item['barcode']]['found'] = True
    changed = True

    if not changed:
    return local_list # Return original list if no changes

    final_list = list(merged_dict.values())
    for i, item in enumerate(final_list):
    item['count'] = i + 1
    return final_list


    # --- API Endpoints for Tampermonkey ---

    @app.route('/get_barcodes', methods=['GET'])
    def get_barcodes():
    """Endpoint for the script to fetch the current list of barcodes."""
    return jsonify(load_barcodes())

    # *** NEW, SAFER ENDPOINT FOR ADDING BARCODES ***
    @app.route('/add_barcode', methods=['POST'])
    def add_barcode():
    """Endpoint for the script to send a single new barcode."""
    new_entry = request.json
    if not new_entry or 'barcode' not in new_entry:
    return jsonify({"status": "error", "message": "Invalid data format."}), 400

    barcodes = load_barcodes()

    # Check for duplicates
    if any(b['barcode'] == new_entry['barcode'] for b in barcodes):
    return jsonify({"status": "success", "message": "Barcode already exists."}), 200

    # Add the new entry and re-assign counts
    barcodes.append(new_entry)
    for i, item in enumerate(barcodes):
    item['count'] = i + 1

    save_barcodes(barcodes)
    print(f"[{time.ctime()}] Added new barcode: {new_entry['barcode']}")
    return jsonify({"status": "success", "message": "Barcode added."}), 201

    @app.route('/update_barcodes', methods=['POST'])
    def update_barcodes():
    """Endpoint for the script to send a full list of barcodes (e.g., after deleting)."""
    new_barcodes = request.json
    if isinstance(new_barcodes, list):
    save_barcodes(new_barcodes)
    return jsonify({"status": "success", "message": "Barcode list updated."}), 200
    return jsonify({"status": "error", "message": "Invalid data format."}), 400


    # --- Network Syncing Logic (UDP Broadcast) ---

    def broadcast_sync():
    """Periodically sends the entire local barcode list to the network."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    while True:
    time.sleep(BROADCAST_INTERVAL)
    barcodes = load_barcodes()
    if barcodes:
    message = json.dumps(barcodes).encode('utf-8')
    try:
    sock.sendto(message, ('', BROADCAST_PORT))
    # print(f"[{time.ctime()}] Sent sync broadcast with {len(barcodes)} items.")
    except Exception as e:
    print(f"Error sending broadcast: {e}")

    def listen_for_sync():
    """Listens for barcode lists from other computers and merges them."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('', BROADCAST_PORT))
    print(f"Listening for sync data on UDP port {BROADCAST_PORT}")
    my_ip = socket.gethostbyname(socket.gethostname())

    while True:
    try:
    data, addr = sock.recvfrom(65507)
    if addr[0] != my_ip:
    received_barcodes = json.loads(data.decode('utf-8'))
    local_barcodes = load_barcodes()
    merged_list = merge_barcodes(local_barcodes, received_barcodes)

    if merged_list is not local_barcodes:
    save_barcodes(merged_list)
    print(f"[{time.ctime()}] Received and merged {len(received_barcodes)} barcodes from {addr[0]}. New total: {len(merged_list)}.")
    except Exception as e:
    print(f"Error receiving sync data: {e}")


    if __name__ == '__main__':
    print("--- Barcode Sync Server ---")
    if not os.path.exists(BARCODES_FILE):
    save_barcodes([])
    print(f"Created empty barcodes file at: {os.path.abspath(BARCODES_FILE)}")

    listener_thread = threading.Thread(target=listen_for_sync, daemon=True)
    listener_thread.start()
    broadcaster_thread = threading.Thread(target=broadcast_sync, daemon=True)
    broadcaster_thread.start()

    print(f"Starting web server for Tampermonkey on http://localhost:{SERVER_PORT}")
    app.run(host='0.0.0.0', port=SERVER_PORT)

  • v3.5.1 2025-10-16
  • v3.5.1 2025-10-16
  • v3.2.0 2025-10-16
  • v3.1.0 2025-10-16
  • v3.0.0 2025-10-16
  • v2.2.0 2025-10-16
  • v2.0.1 2025-10-15
  • v1.9.5 2025-10-04
  • v1.9.4 2025-10-04
  • v1.9.2 2025-10-04
  • v1.9.1 2025-10-04
  • v1.9 2025-10-02
  • v1.7 2025-10-02
  • v1.6 2025-10-02
  • v1.4 2025-10-02
  • v1.2.1 2025-10-02
  • v1.2 2025-10-02