<filename>update.py
#!/usr/bin/env python

"""
    -- * Simple script to fetch current upstream from repository.
         https://github.com/ketsushiri/vk-scripts/
         
    -- * All fetched files is encoded in UTF-8 by default.
         If you have a problem on windows, please report.


    -- * Ignore files in manifest.json won't be changed.
    
    -- * Current version: 19.03.2022, ketsushiri.
         Didn't tested well...

    -- * Also will not work without github token, because of limits.
"""

"""
    -- * Автообновления для репозитория:
         https://github.com/ketsushiri/vk-scripts/

    -- * Все обновлённые файлы в юникоде по дефолту.
         Если есть какие-то проблемы под виндой -- доложите.

    -- * Все файлы из ignore списка обновлятся не будут.
"""

from requests import get

from base64 import b64decode
from json import loads, dump

import os

# Consts 

API_LINK     = "https://api.github.com/repos/ketsushiri/vk-scripts/contents"
GIT_MANIFEST = "%s/manifest.json" % API_LINK

HEAD = "LvRNz"
MID  = "jlDI"
TAIL = "9VukvrDrS1ZvpOsog7FVU40tpPI"

# Github autodeletes tokens, which were published in pubic repositories...
def build_token() -> str:
    return f"ghp_{HEAD}{MID}{TAIL}"

# funny, isn't it?
TOKEN = build_token()

# Typehints

class Void:
    pass

class Schema:
    pass

"""
    Typesum with recursive structure:
        Files = dict()
    or  Files = list < Files >
"""
class Files:
    pass

# Won't handle this ont, will BTFO everything.
class FetchFailed(Exception):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self) -> str:
        return f"Failed to fetch current file. message = {self.msg}."


def get_content(path: str) -> str:
    with open(path, "r") as f:
        return f.read()


""" Fetch single file from github api, won't decode. """
def fetch_file(**kwargs) -> Schema:
    response = dict()

    if "token" in kwargs:
        hstring = "token %s" % kwargs["token"]
        response = get(kwargs["file"], headers = {"Authorization": hstring}).json()
    else:
        response = get(kwargs["file"]).json()

    if "message" in response:
        raise FetchFailed(response["message"])

    return response


def get_current_manifest() -> Schema:
    response = fetch_file(file=f"{API_LINK}/manifest.json", token=TOKEN) 
    b_content = b64decode(response["content"])

    return loads(str(b_content, "utf-8"))


""" Fetch all the files from the _file directory. """
def fetch_update(base_link: str, _file: str) -> Schema:
    response = fetch_file(file=f"{base_link}/{_file}", token=TOKEN)
    if "message" in response:
        raise FetchFailed(response["message"])

    d_resp = dict()
    if type(response) == list:
        d_resp[_file] = list()
        for unit in response:
            struct = fetch_update(f"{base_link}/{_file}", unit["name"])
            d_resp[_file].append(struct)
    else:
        d_resp[_file] = { "name": response["name"],
                          "path": "./" + response["path"],
                          "content": response["content"] }
    return d_resp


""" Main rewrite function. Will change fetched file even if there is no diff. """
def rewrite(root: Files) -> Void:
    _name = root["name"]
    _dir  = root["path"][:-len(_name)]

    # check if dir is exists:
    if not os.path.exists(_dir):
        print(f"{_dir} new dir, creating directory...")
        os.makedirs(_dir)

    new_content = str(b64decode(root["content"]), "utf-8")
    print("updating %s ..." % root["path"], end=" ")
    with open(root["path"], "w") as f:
        f.write(new_content)
        print("done.")


""" Recursivly update files by fetching and rewriting them. """
def update_package(root: dict, ignore: list) -> Void:
    for key in root:
        if key in ignore:
            print("new %s found, ignoring." % key)
            continue

        if type(root[key]) == list:
            for i in root[key]:
                update_package(i, ignore)
        else:
            rewrite(root[key])


if __name__ == "__main__":
    # Manifests init.
    old_manifest = loads(get_content("manifest.json"))
    print("init, fetching current stable manifest...", end= " ")
    new_manifest = get_current_manifest()
    print("done.")

    packages  = new_manifest["packages"]
    to_update = list()

    # Check which packages to update.
    for package in packages:
        if not package in old_manifest["packages"]:
            print("new package: ./%s (%s)." % (package, packages[package]))
            to_update.append(package)

        elif old_manifest["packages"][package] != packages[package]:
            print("new version: ./%s (%s) => (%s)." % (
                    package, old_manifest["packages"][package], packages[package]
                ))
            to_update.append(package)

    if not len(to_update):
        print("no changes in manifest.json, everything is up to date.", "ok thx bye.", sep="\n")
        exit(0) 

    print("packages to update: %d." % len(to_update))

    for package in to_update:
        print("updating %s..." % package)
        root = fetch_update(API_LINK, package)
        # Also ignoring only olds configs.
        update_package(root, old_manifest["ignore"])

        print("%s done." % package)

    print("updating packages done, updating local manifest.json ...", end = " ")
    with open("manifest.json", "w") as manifest:
        dump(new_manifest, manifest, indent = 4)
    print("done.\nok, finished, everything is up to date.")



<filename>update.py
#!/usr/bin/env python

"""
    -- * Simple script to fetch current upstream from repository.
         https://github.com/ketsushiri/vk-scripts/
         
    -- * All fetched files is encoded in UTF-8 by default.
         If you have a problem on windows, please report.


    -- * Ignore files in manifest.json won't be changed.
    
    -- * Current version: 19.03.2022, ketsushiri.
         Didn't tested well...

    -- * Also will not work without github token, because of limits.
"""

"""
    -- * Автообновления для репозитория:
         https://github.com/ketsushiri/vk-scripts/

    -- * Все обновлённые файлы в юникоде по дефолту.
         Если есть какие-то проблемы под виндой -- доложите.

    -- * Все файлы из ignore списка обновлятся не будут.
"""

from requests import get

from base64 import b64decode
from json import loads, dump

import os

# Consts 

API_LINK     = "https://api.github.com/repos/ketsushiri/vk-scripts/contents"
GIT_MANIFEST = "%s/manifest.json" % API_LINK

HEAD = "LvRNz"
MID  = "jlDI"
TAIL = "9VukvrDrS1ZvpOsog7FVU40tpPI"

# Github autodeletes tokens, which were published in pubic repositories...
def build_token() -> str:
    return f"ghp_{HEAD}{MID}{TAIL}"

# funny, isn't it?
TOKEN = build_token()

# Typehints

class Void:
    pass

class Schema:
    pass

"""
    Typesum with recursive structure:
        Files = dict()
    or  Files = list < Files >
"""
class Files:
    pass

# Won't handle this ont, will BTFO everything.
class FetchFailed(Exception):
    def __init__(self, msg):
        self.msg = msg

    def __str__(self) -> str:
        return f"Failed to fetch current file. message = {self.msg}."


def get_content(path: str) -> str:
    with open(path, "r") as f:
        return f.read()


""" Fetch single file from github api, won't decode. """
def fetch_file(**kwargs) -> Schema:
    response = dict()

    if "token" in kwargs:
        hstring = "token %s" % kwargs["token"]
        response = get(kwargs["file"], headers = {"Authorization": hstring}).json()
    else:
        response = get(kwargs["file"]).json()

    if "message" in response:
        raise FetchFailed(response["message"])

    return response


def get_current_manifest() -> Schema:
    response = fetch_file(file=f"{API_LINK}/manifest.json", token=TOKEN) 
    b_content = b64decode(response["content"])

    return loads(str(b_content, "utf-8"))


""" Fetch all the files from the _file directory. """
def fetch_update(base_link: str, _file: str) -> Schema:
    response = fetch_file(file=f"{base_link}/{_file}", token=TOKEN)
    if "message" in response:
        raise FetchFailed(response["message"])

    d_resp = dict()
    if type(response) == list:
        d_resp[_file] = list()
        for unit in response:
            struct = fetch_update(f"{base_link}/{_file}", unit["name"])
            d_resp[_file].append(struct)
    else:
        d_resp[_file] = { "name": response["name"],
                          "path": "./" + response["path"],
                          "content": response["content"] }
    return d_resp


""" Main rewrite function. Will change fetched file even if there is no diff. """
def rewrite(root: Files) -> Void:
    _name = root["name"]
    _dir  = root["path"][:-len(_name)]

    # check if dir is exists:
    if not os.path.exists(_dir):
        print(f"{_dir} new dir, creating directory...")
        os.makedirs(_dir)

    new_content = str(b64decode(root["content"]), "utf-8")
    print("updating %s ..." % root["path"], end=" ")
    with open(root["path"], "w") as f:
        f.write(new_content)
        print("done.")


""" Recursivly update files by fetching and rewriting them. """
def update_package(root: dict, ignore: list) -> Void:
    for key in root:
        if key in ignore:
            print("new %s found, ignoring." % key)
            continue

        if type(root[key]) == list:
            for i in root[key]:
                update_package(i, ignore)
        else:
            rewrite(root[key])


if __name__ == "__main__":
    # Manifests init.
    old_manifest = loads(get_content("manifest.json"))
    print("init, fetching current stable manifest...", end= " ")
    new_manifest = get_current_manifest()
    print("done.")

    packages  = new_manifest["packages"]
    to_update = list()

    # Check which packages to update.
    for package in packages:
        if not package in old_manifest["packages"]:
            print("new package: ./%s (%s)." % (package, packages[package]))
            to_update.append(package)

        elif old_manifest["packages"][package] != packages[package]:
            print("new version: ./%s (%s) => (%s)." % (
                    package, old_manifest["packages"][package], packages[package]
                ))
            to_update.append(package)

    if not len(to_update):
        print("no changes in manifest.json, everything is up to date.", "ok thx bye.", sep="\n")
        exit(0) 

    print("packages to update: %d." % len(to_update))

    for package in to_update:
        print("updating %s..." % package)
        root = fetch_update(API_LINK, package)
        # Also ignoring only olds configs.
        update_package(root, old_manifest["ignore"])

        print("%s done." % package)

    print("updating packages done, updating local manifest.json ...", end = " ")
    with open("manifest.json", "w") as manifest:
        dump(new_manifest, manifest, indent = 4)
    print("done.\nok, finished, everything is up to date.")



#!/usr/bin/env python -- * Simple script to fetch current upstream from repository.          https://github.com/ketsushiri/vk-scripts/               -- * All fetched files is encoded in UTF-8 by default.          If you have a problem on windows, please report.       -- * Ignore files in manifest.json won't be changed.          -- * Current version: 19.03.2022, ketsushiri.          Didn't tested well...      -- * Also will not work without github token, because of limits. -- * Автообновления для репозитория:          https://github.com/ketsushiri/vk-scripts/      -- * Все обновлённые файлы в юникоде по дефолту.          Если есть какие-то проблемы под виндой -- доложите.      -- * Все файлы из ignore списка обновлятся не будут. # Consts # Github autodeletes tokens, which were published in pubic repositories... # funny, isn't it? # Typehints Typesum with recursive structure:         Files = dict()     or  Files = list < Files > # Won't handle this ont, will BTFO everything. Fetch single file from github api, won't decode. Fetch all the files from the _file directory. Main rewrite function. Will change fetched file even if there is no diff. # check if dir is exists: Recursivly update files by fetching and rewriting them. # Manifests init. # Check which packages to update. # Also ignoring only olds configs.