From 924b1e593c2c6d66497e569e85a473f2ca632d8a Mon Sep 17 00:00:00 2001 From: blob42 Date: Fri, 6 Jan 2023 16:13:52 +0100 Subject: [PATCH] initial commit --- README.md | 43 ++++++++++++++++ cgpt.py | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 README.md create mode 100755 cgpt.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..05ce7f4 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# Awesome ChatGPT Prompts CLI + +This is a command line tool that allows you to select a prompt to use with +ChatGPT from the [Awesome ChatGPT +Prompts](https://raw.githubusercontent.com/f/awesome-chatgpt-prompts) + + +## Installation + +To install the dependencies needed to run this program, run: + +`pip install -r requirements.txt` + +You will also need to have `fzf` locally installed. + +## Usage + +To use this program, run: + +`cgpt.py [COMMAND]` + +If no command is provided, it will present you with a list of prompts that you +can choose from. Use the up and down arrow keys to navigate the list and the +Enter key to select a prompt. + +You can also use the following commands: + +- `add`: Add a custom prompt to the list. +- `delete`: Delete a custom prompt from the list. +- `update`: Update the list of prompts from the remote repository. + +## Features/TODO + +- [x] Update the list of prompts from the remote repository. +- [x] Add support for custom prompts +- [ ] Create a pull request to add custom prompts to the + remote repository. + +## Credits +The prompts in this tool are taken from the [awesome-chatgpt-prompts](https://github.com/f/awesome-chatgpt-prompts) repository. + + + diff --git a/cgpt.py b/cgpt.py new file mode 100755 index 0000000..7e66556 --- /dev/null +++ b/cgpt.py @@ -0,0 +1,143 @@ +#!/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 fzf import Fzf, 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 = "echo {}" + preview_window = "right:50%" + act = chooser.prompt(prompts.keys(), header=header, preview=preview, preview_window=preview_window) + 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() +