Hi everyone,

let me first introduce myself. My name is Patrick. I'm long time user of Scid vs. PC, junior software engineer and amateur chess player (FIDE ~2100). I'm not sure whether my message is of interest to any of you, or I am sharing it on the wrong place perhaps.

I've been using the twic2scid.py script written for python 2.x for some time. Upon a recent fresh OS installation, by default I did not have python2.x installed, so I rewrote the script for python 3.x. If you are interested, you can find it in the attachment.

Meanwhile, I also wrote a pgn2scid.py script for merging a folder of pgn files (or a single pgn file) into a scid database, which you can also find in the attachment.

Best regards,
Patrick



# Append games from a single PGN file or a folder with PGN files to an existing
# Scid database and perform spellchecking

# By Patrick Nikić

# NOTE: It works recursively i.e. also from the folders inside the folder etc.

# NOTE: This program comes with absolutely NO WARRANTY.  If anything
# goes wrong, it may delete your database entirely instead of adding
# to it!  I recommend backing up your database, trying it out, and
# then adding a "last week rollback" type of copy command to your
# cronjob, just to make sure.

import glob
import os
import sys
import tempfile

from argparse import ArgumentParser, RawTextHelpFormatter

usage = "Example usage:\n" \
    "  pgn2scid.py -f ~/recent_pgns_folder ~/scidbases/twic -s ~/scidbases/spelling.ssp\n" \
    "    --merges all .PGN files from given folder into specified scid database and spelling file.\n" \
    "  pgn2scid.py -f ~/torunament.pgn ~/scidbases/twic -s ~/scidbases/spelling.ssp -b\n" \
    "    --merges the given .PGN file into specified scid database and spelling file. " \
    "A backup copy of the database is saved.\n" \

parser = ArgumentParser(description=usage, formatter_class=RawTextHelpFormatter)
parser.add_argument("-f", "--folder", dest="folder", required=True,
                    help="specify the PGN file to merge or folder containing PGN files for merging")

parser.add_argument("-d", "--database", dest="database", required=True,
                    help="specify the scid database to merge into. Note that this omits the extension .si4 of the database.")

parser.add_argument("-s", "--spelling", dest="spelling", default="spelling.ssp", required=True,
                    help="specifies the spelling file for meta corrections. Default value is 'spelling.ssp'.")

parser.add_argument("-b", "--backup", action="store_true", dest="backup",
                    help="stores a backup the specified database")


options = parser.parse_args()
os.environ["PATH"] += ":/usr/local/bin"

scid_database = options.database
scid_spelling = options.spelling
backup_flag = options.backup
folder_pgn = os.path.abspath(options.folder)

pgn_fd, pgn_path = tempfile.mkstemp(".pgn")
if os.path.isdir(folder_pgn):
    print(f"Concatenating all the PGN(s) from {folder_pgn}...")
    with open(pgn_fd, "wb") as all_pgns:
        for dirpath, dirnames, filenames in os.walk(folder_pgn):
            for f in filenames:
                full_path = os.path.join(dirpath, f)
                if full_path.endswith(".pgn"):
                    print(f"Appending {full_path}...")
                    with open(full_path, "rb") as one_pgn:
                        all_pgns.write(one_pgn.read())
elif os.path.isfile(folder_pgn):
    with open(pgn_fd, "wb") as all_pgns:
        with open(folder_pgn, "rb") as one_pgn:
            all_pgns.write(one_pgn.read())
else:
    print("Neither a file nor a folder was given!")
    os.unlink(pgn_path)
    sys.exit(1)

print("Converting PGN file to a temporary scid database...")
os.system(f"pgnscid -f {pgn_path} {scid_database}.new")
os.unlink(pgn_path)

os.system(f"scmerge {scid_database}.old {scid_database}")
list(map(os.unlink, glob.glob(f"{scid_database}.s*")))

print(f"Merging all games with {scid_database}...")
os.system(f"scmerge {scid_database} {scid_database}.new {scid_database}.old")
list(map(os.unlink, glob.glob(f"{scid_database}.new.s*")))

if backup_flag:
    print(f"Keeping backup of specified database as {scid_database}.old...")
else:
    list(map(os.unlink, glob.glob(f"{scid_database}.old.s*")))

print("Spell checking the new database...")
os.system(f"sc_spell {scid_database} {scid_spelling}")

# Download the current week's TWIC games and append them to an existing
# Scid database and perform spellchecking.

# Original script written by John Wiegley

# Modifications by Maksim Grinman:
# 3/20/2013: Updated to work with the new TWIC site at http://www.theweekinchess.com/twic
# 3/23/2013: Updated to support optional flags -a and -n.

# Modifications by Patrick Nikić:
# 5/20/2020: Port script to python3

# NOTE: This program comes with absolutely NO WARRANTY.  If anything
# goes wrong, it may delete your database entirely instead of adding
# to it!  I recommend backing up your database, trying it out, and
# then adding a "last week rollback" type of copy command to your
# cronjob, just to make sure.

import glob
import os
import re
import shutil
import sys
import tempfile
import urllib.request
import zipfile

from argparse import ArgumentParser, RawTextHelpFormatter

usage = "Example usage:\n" \
    "  twic2scid.py -n 3 -d ~/scidbases/twic -s ~/scidbases/spelling.ssp\n" \
    "    --merges latest 3 pgns into specified scid database and spelling file.\n" \
    "  twic2scid.py -a\n" \
    "    --merges all pgns available into the default database with the default spelling file.\n" \
    "  twic2scid.py --latestn=5 --spelling=another_spelling.ssp\n" \
    "    --merges latest 5 pgns into the default database 'twic.si4' in current directory, and uses " \
    "spelling file 'another_spelling.ssp' in current directory."

parser = ArgumentParser(description=usage, formatter_class=RawTextHelpFormatter)
parser.add_argument("-a", "--all", action="store_true", dest="all",
                    help="gets all pgn archives on the page. Overrides -n if specified.")

parser.add_argument("-n", "--latestn", type=int, dest="latestn",
                    help="gets LATESTN archives. LATESTN must be an integer. If LATESTN is greater than the number of pgn archives found on the twic page, this is equivalent to --all. If LATESTN is zero, this option is ignored.")

parser.add_argument("-d", "--database", dest="database", default="twic",
                    help="specify the scid database to merge into. Default value is 'twic'. Note that this omits the extension .si4 of the database.")

parser.add_argument("-s", "--spelling", dest="spelling", default="spelling.ssp",
                    help="specifies the spelling file for meta corrections. Default value is 'spelling.ssp'.")


options = parser.parse_args()
os.environ['PATH'] += ":/usr/local/bin"

if options.all or options.latestn == 0 or options.latestn == None:
    options.latestn = None
else:
    options.latestn = abs(options.latestn)

scid_database = options.database
scid_spelling = options.spelling

print("Downloading the Week in Chess main page...")

# list of pgn links found
pgn_links = []
found = 0

with urllib.request.urlopen("https://www.theweekinchess.com/twic";) as url:
    for line in url.readlines():
        # Match a https:// string until encounter of " symbol
        line = line.decode()
        match = re.search("https://[^\"]+";, line)
        if match:
            # Choose the zip that contains PGN (not CBV, Text or else)
            pgn = re.search(">PGN<", line)
            if (pgn):
                pgn_links.append(match.group(0))
                found += 1

                if options.all:
                    continue
                elif options.latestn and found != options.latestn:
                    continue
                else:
                    break

if not found:
    print("Could not find PGN zipfile in twic.html!")
    sys.exit(1)

# lftp is preferred in the following code, since it does all the retrying and status display

print(f"Getting PGN archives {pgn_links}")

# will hold scid databases to be merged
databases = []
    
# will hold zips downloaded, each zip should contain a pgn file
pgn_zips = []

# will hold temporary zip files to be cleaned up after use
containers = []

for link in pgn_links:
    zip_fd, zip_path =  tempfile.mkstemp(".zip")
    containers.append(zip_path)

    if os.path.isfile("usr/bin/lftp"):
        status = os.system(f"lftp -c 'get {link} -o {zip_path}; quit'")
    else:
        status = os.system(f"wget -O {zip_path} {link}")

    if status != 0:
        print("lftp or wget not working, retrying directly...")
        with open(zip_fd, "wb") as f:
            with urllib.request.urlopen(link) as response:
                shutil.copyfileobj(response, f)

    pgn_zips.append(zipfile.ZipFile(zip_path))

print("Unzipping and converting to scid databases...")
for pgn_zip in pgn_zips:
    for elem in pgn_zip.namelist():
        if re.search("\.pgn$", elem):
            pgn_fd, pgn_path = tempfile.mkstemp(".pgn")
            with open(pgn_fd, "wb") as pgn:
                pgn.write(pgn_zip.read(elem))

            db_fd, db_path = tempfile.mkstemp()
            os.system(f"pgnscid -f {pgn_path} {db_path}")
            databases.append(db_path)

            os.unlink(pgn_path)
    pgn_zip.close()
    
list(map(os.unlink, containers))

print(f"Merging databases into {scid_database}.new...")
if databases:
    status = os.system(f"scmerge {scid_database}.new {scid_database} {' '.join(databases)}")

    for db in databases:
        list(map(os.unlink, glob.glob(f"{db}*")))

    if status == 0:
        print(f"Moving new database to {scid_database}...")
        list(map(os.unlink, glob.glob(f"{scid_database}.s*")))
        os.system(f"scmerge {scid_database} {scid_database}.new")
        list(map(os.unlink, glob.glob(f"{scid_database}.new.s*")))

        print("Spell checking the new database...")
        os.system(f"sc_spell {scid_database} {scid_spelling}")
_______________________________________________
Scidvspc-users mailing list
Scidvspc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/scidvspc-users

Reply via email to