You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
4.2 KiB
Python

#!/usr/bin/env python3
import os
import sys
import requests
import csv
# We will need to import the `click` package to build the CLI.
import click
# We will also need to import the `fzf` package to use the `fzf` command.
from pyfzf.pyfzf import FzfPrompt as Fzf
XDG_DATA_HOME = os.environ.get('XDG_DATA_HOME', os.path.expanduser('~/.local/share'))
PROMPTS_URL = "https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv"
CACHE_LOCATION = os.path.join(XDG_DATA_HOME, "chatgpt-prompts", "prompts.csv")
PROMPTS_REPO_URL = "https://github.com/f/awesome-chatgpt-prompts"
REPO_PROMPTS_RELPATH = "prompts.csv"
# save custom prompts to my-prompts.csv
CUSTOM_PROMPTS = os.path.join(XDG_DATA_HOME, "chatgpt-prompts", "my-prompts.csv")
def cache_prompts(update=False):
'''
if the prompts are not cached, download them and cache them locally
'''
if not os.path.exists(CACHE_LOCATION) or update:
print("Downloading remote prompts...")
os.makedirs(os.path.dirname(CACHE_LOCATION), exist_ok=True)
with open(CACHE_LOCATION, "w") as f:
f.write(requests.get(PROMPTS_URL).text)
f.close()
def load_prompts(custom_only=False):
'''
Loads the prompts from the cache. if the cache is empty, download the prompts.
The prompts csv contains two columns separated by a comma in the form "act", "prompt"
Returns the list of prompts as tuples
'''
cache_prompts()
prompts = {}
if not custom_only:
with open(CACHE_LOCATION, "r") as f:
prompts = f.readlines()
# load the prompts into a list of tuples
prompts = [tuple(prompt.strip().split(",")) for prompt in prompts]
# transform into a dict of acts keys and prompt values
prompts = {prompt[0]: prompt[1] for prompt in prompts[1:]}
f.close()
with open(CUSTOM_PROMPTS, "r") as f:
custom_prompts = f.readlines()
custom_prompts = [tuple(prompt.strip().split(",")) for prompt in custom_prompts]
custom_prompts = {prompt[0]: prompt[1] for prompt in custom_prompts[1:]}
prompts.update(custom_prompts)
f.close()
return prompts
# save custom prompts to CUSTOM_PROMPTS
def save_prompt(act, prompt):
# if custom prompts is empty initialize it with a the csv header
if not os.path.exists(CUSTOM_PROMPTS):
with open(CUSTOM_PROMPTS, "w") as f:
header = '"act","prompt"\n'
f.write(header)
f.close()
with open(CUSTOM_PROMPTS, "a") as f:
f.write(f'"{act}","{prompt}"\n')
f.close()
@click.group()
def cli():
pass
# select and return a tuple (act, prompt)
def choose_prompt(custom_only=False):
prompts = load_prompts(custom_only)
# load custom prompts
chooser = Fzf()
header = "'Select an act'"
# preview the prompt of the selected act
preview = f"'cat {CACHE_LOCATION} | grep {{1}} | cut -d, -f 2'"
preview_window = "right:50%,wrap"
act = chooser.prompt(prompts.keys(), '--header={} --preview-window={} --preview {}'.format(header, preview_window, preview,))
prompt = prompts.get(act[0])
return (act[0], prompt)
def show_prompts():
act, prompt = choose_prompt()
print(prompt)
# update refreshes the prompts from the remote repo
@click.command()
def update():
cache_prompts(update=True)
# We will create a function called `pr` that will be executed when the `pr`
# command is provided.
@click.command()
def pr():
print("[TODO] Opening a PR to add your prompt to the prompts repo")
# The add command allows the user to define a new prompt by providing the act and the prompt
@click.command()
def add():
act = input("Enter the act title: ")
prompt = input("Enter the prompt: ")
save_prompt(act, prompt)
# We will add the `add`, `update`, and `pr` functions to the `show_prompts`
# function.
cli.add_command(add)
cli.add_command(update)
cli.add_command(pr)
# We will execute the `show_prompts` function if the script is executed directly
# without any command provided
if __name__ == "__main__":
# if no command provided call show_prompts
if len(sys.argv) == 1:
show_prompts()
else:
cli()