diff --git a/.gitignore b/.gitignore index d50a09f..ff50891 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env __pycache__/ +*egg-info/ diff --git a/ai_getter/__init__.py b/ai_getter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/ai_getter/main.py similarity index 64% rename from main.py rename to ai_getter/main.py index 35d0543..ed5506b 100644 --- a/main.py +++ b/ai_getter/main.py @@ -4,8 +4,10 @@ import pathlib as pl import sys import openai +import pyperclip +from rich.pretty import pprint -from save import save_images_from_openai, upload_to_s3, save_output +from .save import save_images_from_openai, upload_to_s3, save_output openai.organization = os.getenv("OPENAI_ORG") openai.api_key = os.getenv("OPENAI_TOKEN") @@ -28,6 +30,7 @@ def chat(prompt: str, save_path: pl.Path = SAVE_PATH, save_to_s3: bool = False) if S3_BUCKET is None: raise NoBucket("Please provide AI_GETTER_S3_BUCKET in .env") upload_to_s3(S3_BUCKET, str(fp), str(fp)) + pprint(response) return content # type: ignore @@ -41,50 +44,68 @@ def generate_images(prompt: str, num_images: int, save_path: pl.Path = SAVE_PATH raise NoBucket("Please provide AI_GETTER_S3_BUCKET in .env") for idx, fp in enumerate(file_paths): upload_to_s3(S3_BUCKET, fp, f"{prompt}-{dt.date.today()}-{idx}") + pprint(res) return res # type: ignore +def print_help(): + print(""" +Usage: + aig help + aig image [--clip] --num-images [--save-path ] [--s3] + aig text [--clip] [--save-path ] [--s3] + + (--clip will get the prompt from your clipboard's contents) + """) + + def main(): args = sys.argv - if len(args) < 3: - print("Please provide and a prompt") - sys.exit() + if len(args) < 3 or args[1] == "help": + return print_help() + + typ, prompt, *the_rest = args[1:] - typ, prompt = args[1:3] if typ not in "image text".split(): - print("Please provide and a prompt") - sys.exit() + return print_help() - if "--save-path" in args: - save_path = pl.Path(args[args.index("--save-path") + 1]) - else: - save_path = SAVE_PATH + if len(the_rest) == 0 and prompt == "--clip": + prompt = pyperclip.paste() + elif "--clip" in the_rest: + prompt = prompt + " " + pyperclip.paste() + + save_path = SAVE_PATH + if "--save-path" in the_rest: + try: + save_path = pl.Path(the_rest[the_rest.index("--save-path") + 1]) + except IndexError: + print("Please provide a path after --save-path") + return save_to_s3 = False - if "--save-to-s3" in args: + if "--s3" in the_rest: + if S3_BUCKET is None: + print("Please provide AI_GETTER_S3_BUCKET in .env") + return save_to_s3 = True - if save_to_s3 and S3_BUCKET is None: - print("Please provide AI_GETTER_S3_BUCKET in .env") - sys.exit() match typ: case "image": if "--num-images" not in args: print("Please provide --num-images") - sys.exit() + return num_images = int(args[args.index("--num-images") + 1]) try: generate_images(prompt, num_images, save_path, save_to_s3) except ValueError as e: print(str(e)) - sys.exit() + return case "text": chat(prompt, save_path, save_to_s3) case _: - print("Please provide and a prompt") - sys.exit() + return print_help() print("Okay, we're done!") if __name__ == "__main__": diff --git a/save.py b/ai_getter/save.py similarity index 82% rename from save.py rename to ai_getter/save.py index 7c8e200..ce800ef 100644 --- a/save.py +++ b/ai_getter/save.py @@ -18,12 +18,21 @@ def make_fp_from_prompt( index: int | None = None, ) -> pl.Path: prompt_fn = ( - prompt.replace(" ", "_") + prompt.replace(" ", "") .replace("'", "") + .replace('"', "") .replace(".", "") .replace(",", "") + .replace("<", "") + .replace(">", "") + .replace("\\", "") + .replace(";", "") + .replace("!", "") + .replace("{", "") + .replace("}", "") + .replace("/", "") .lower() - )[: 225 - len(str(save_path))] + )[: 100 - len(str(save_path))] if index is not None: prompt_fn = f"{prompt_fn}{index}" prompt_fn = f"{prompt_fn}-{dt.datetime.now()}" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..374b58c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +requires = [ + "setuptools>=42", + "wheel" +] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f236601 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,26 @@ +-e git+https://github.com/zevaverbach/ai_getter@bc472274f6f10c180daa9ee267247cb51ea4ea15#egg=ai_getter +aiohttp==3.8.4 +aiosignal==1.3.1 +async-timeout==4.0.2 +attrs==22.2.0 +boto3==1.26.104 +botocore==1.29.104 +certifi==2022.12.7 +charset-normalizer==3.1.0 +frozenlist==1.3.3 +idna==3.4 +jmespath==1.0.1 +markdown-it-py==2.2.0 +mdurl==0.1.2 +multidict==6.0.4 +openai==0.27.2 +Pygments==2.14.0 +pyperclip==1.8.2 +python-dateutil==2.8.2 +requests==2.28.2 +rich==13.3.3 +s3transfer==0.6.0 +six==1.16.0 +tqdm==4.65.0 +urllib3==1.26.15 +yarl==1.8.2 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f926fd2 --- /dev/null +++ b/setup.py @@ -0,0 +1,28 @@ +import pathlib as pl +from setuptools import setup + +setup( + name="ai_getter", + version="0.0.1", + description="A CLI for publishing sites to Netlify and assigning custom domains to them.", + author="Zev Averbach", + author_email="zev@averba.ch", + description_file="README.md", + long_description=pl.Path("README.md").read_text(), + long_description_content_type="text/markdown", + license="MIT", + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + ], + packages=["ai_getter"], + include_package_data=True, + install_requires=["requests", "openai", "requests"], + python_requires=">=3.10", # only because we're using | instead of typing.Union; otherwise >= 3.9 + url="https://github.com/zevaverbach/ai_getter", + entry_points={"console_scripts": ["aig=ai_getter.main:main"]}, +)