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.

184 lines
4.9 KiB
Python

1 year ago
#!/usr/bin/env python3
import os
import sys
import requests
import time
1 year ago
# We will need to import the `click` package to build the CLI.
import click
1 year ago
# We will also need to import the `fzf` package to use the `fzf` command.
from pyfzf.pyfzf import FzfPrompt as Fzf
1 year ago
XDG_CONFIG_HOME = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
CONFIG_DIR = os.path.join(XDG_CONFIG_HOME, "cgpt")
1 year ago
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"
UPDATE_INTERVAL = 1 # update the prompts every 1 days
PR_HELP = """
helper to create a PR from a custom prompt. The output can be appended to the prompts.csv file in the prompts repo. You can
pipe the output of this command to pbcopy or xclip to copy it to your
clipboard.
For example: `./cgpt.py pr | xclip -selection cliboard`
"""
1 year ago
# save custom prompts to my-prompts.csv
CUSTOM_PROMPTS = os.path.join(XDG_DATA_HOME, "chatgpt-prompts", "my-prompts.csv")
def check_update():
if not os.path.exists(CACHE_LOCATION):
return
last_update = os.path.getmtime(CACHE_LOCATION)
# if last update older than UPDATE_INTERVAL days
if time.time() - last_update > UPDATE_INTERVAL * 24 * 60 * 60:
cache_prompts(update=True)
1 year ago
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()
# init custom prompts if not exists
if not os.path.exists(CUSTOM_PROMPTS):
with open(CUSTOM_PROMPTS, "w") as f:
header = '"act","prompt"\n'
f.write(header)
f.close()
def init_config():
if not os.path.exists(CONFIG_DIR):
os.makedirs(CONFIG_DIR)
import csv
1 year ago
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", newline='') as f:
prompts_reader = csv.reader(f)
next(prompts_reader) # skip header row
prompts = {row[0]: row[1] for row in prompts_reader}
1 year ago
f.close()
with open(CUSTOM_PROMPTS, "r", newline='') as f:
custom_prompts_reader = csv.reader(f)
next(custom_prompts_reader) # skip header row
custom_prompts = {row[0]: row[1] for row in custom_prompts_reader}
1 year ago
prompts.update(custom_prompts)
f.close()
return prompts
# save custom prompts to CUSTOM_PROMPTS
def save_prompt(act, prompt):
with open(CUSTOM_PROMPTS, "a") as f:
f.write(f'"{act}","{prompt}"\n')
f.close()
@click.group()
def cli():
pass
class Fzfer:
def __init__(self, prompts):
self.act_prompt = prompts
self.fzf = Fzf()
self.header = "act,prompt"
self.preview = f"'cat {CACHE_LOCATION} | grep \'{{}}\' '"
# self.preview = f"{{}}"
self.preview_window = "right:50%,wrap"
1 year ago
def show(self):
return self.fzf.prompt(self.act_prompt, '--header={} --preview-window={} --preview {}'.format(self.header, self.preview_window, self.preview))
# select and return a tuple (act, prompt)
def choose_prompt(custom_only=False):
prompts = load_prompts(custom_only)
f = Fzfer(prompts)
act = f.show()
1 year ago
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(help="update the prompts from the remote repo")
1 year ago
def update():
cache_prompts(update=True)
@click.command(help=PR_HELP)
def pr():
'''
Helper to create a PR from a custom prompt
'''
# select a custom prompt
act, prompt = choose_prompt(custom_only=True)
prompt = f'{act},{prompt}'
print(prompt)
1 year ago
@click.command()
def add():
act = input("Enter the act title: ")
prompt = input("Enter the prompt: ")
save_prompt(act, prompt)
@click.command(help="Show my custom prompts")
def my():
'''
Pick custom prompts
'''
prompts = load_prompts(custom_only=True)
f = Fzfer(prompts)
act = f.show()
prompt = prompts.get(act[0])
print(prompt)
1 year ago
cli.add_command(add)
cli.add_command(update)
cli.add_command(pr)
cli.add_command(my)
1 year ago
if __name__ == "__main__":
check_update()
1 year ago
if len(sys.argv) == 1:
show_prompts()
else:
cli()