diff --git a/.github/keywords/keywords-generator.py b/.github/keywords/keywords-generator.py new file mode 100644 index 0000000000..bbf234be0c --- /dev/null +++ b/.github/keywords/keywords-generator.py @@ -0,0 +1,112 @@ +import os +import json +import openai +import subprocess +from dotenv import load_dotenv + +# Load environment variables from the .env file +load_dotenv() + +# Set up the OpenAI API key +openai.api_key = os.getenv("OPENAI_API_KEY") + +# Path to the main folder (the "icons" folder) +main_folder = "./icons" + +# JSON file where synonyms will be stored +synonyms_json_file = "icons/icons-keywords.json" + +# Load the JSON file if it already exists +if os.path.exists(synonyms_json_file): + with open(synonyms_json_file, "r", encoding="utf-8") as f: + synonyms_dictionary = json.load(f) +else: + synonyms_dictionary = {} + +# Remove common style indicators from the filename and return +def preprocess_filename(filename): + return filename.replace("-filled.svg", "").replace("-light.svg", "").replace("-regular.svg", "") + +# Function to recursively list all unique SVG filenames without their paths +def list_concepts(folder): + concepts = set() # Use a set to avoid duplicates + for root, dirs, files in os.walk(folder): + # Filter and preprocess SVG filenames before adding to the set + for file in files: + if file.endswith('.svg') and not file.startswith('.'): + processed_file = preprocess_filename(file) + concepts.add(processed_file) + return list(concepts) # Convert set to list before returning + +# Function to generate synonyms using GPT +def generate_synonyms(concept): + prompt = f"Generate 12 synonyms for the concept '{concept}' mixing English, Spanish, Portuguese, and German (in this order). Return them as a plain list of words, without quotes, numbering, or separation by language. the order of the synonyms should be English, Spanish, Portuguese, and German. For example: alert lamp cross, warning light plus, signal illumination cross, luz de alarma cruz, luz de advertencia plus, iluminación de señal cruz, Alarmleuchte Kreuz, Warnlicht plus, Signalbeleuchtung Kreuz" + + response = openai.ChatCompletion.create( + model="gpt-4", + messages=[ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": prompt} + ], + max_tokens=100, + temperature=0.7, + ) + + # Get the generated response + raw_synonyms = response['choices'][0]['message']['content'].strip() + + # Clean the output, removing unnecessary characters and convert it to a list + synonyms = [synonym.strip(' "[]') for synonym in raw_synonyms.split(',')] + + return synonyms + +# Get concepts from the icons folder +concepts = set(list_concepts(main_folder)) # Convert to set for efficiency + +# Counter to know how many new concepts have been processed +new_concepts = 0 + +# Remove entries in synonyms_dictionary that no longer have corresponding icons +keys_to_remove = [key for key in synonyms_dictionary if key not in concepts] +for key in keys_to_remove: + del synonyms_dictionary[key] + print(f"Concept removed: {key}") + +# Update the JSON file only with new concepts +for concept in concepts: + if concept not in synonyms_dictionary: + print(f"Generating synonyms for: {concept}") + try: + # Generate synonyms using GPT + generated_synonyms = generate_synonyms(concept) + # Save the synonyms in the dictionary + synonyms_dictionary[concept] = generated_synonyms + new_concepts += 1 + print(f"Concept generated: {concept} - Synonyms: {generated_synonyms}") + except Exception as e: + print(f"Error generating synonyms for {concept}: {e}") + # In case of error, save generic synonyms to avoid leaving it empty + synonyms_dictionary[concept] = ["synonym1", "synonym2", "synonym3"] + print(f"Concept generated with generic synonyms: {concept}") + +# Only save if there are new concepts or if concepts have been removed +if new_concepts > 0 or keys_to_remove: + # Save the updated and alphabetically sorted dictionary in the JSON file + with open(synonyms_json_file, "w", encoding="utf-8") as f: + json.dump(synonyms_dictionary, f, ensure_ascii=False, indent=4, sort_keys=True) + print(f"{new_concepts} new concepts have been generated.") + print(f"{len(keys_to_remove)} obsolete concepts have been removed.") +else: + print("No new concepts or obsolete concepts found.") + +# Run Prettier to format the JSON file +try: + subprocess.run(["npx", "prettier", "--write", synonyms_json_file], check=True) + print(f"The file {synonyms_json_file} has been formatted with Prettier.") +except subprocess.CalledProcessError as e: + print(f"Error formatting the file with Prettier: {e}") + +# Count the total number of concepts +total_concepts = len(concepts) +print(f"Total concepts processed: {total_concepts}") +print("Process completed. The icons-keywords.json file has been updated and sorted alphabetically.") diff --git a/.github/workflows/auto-generator.yml b/.github/workflows/auto-generator.yml index 28b18a1f8e..f241609b30 100644 --- a/.github/workflows/auto-generator.yml +++ b/.github/workflows/auto-generator.yml @@ -27,7 +27,13 @@ jobs: - run: sudo python3 .github/md-generator/generate_markdown.py icons + - name: Check for changes + id: git_status + run: | + git diff --exit-code || echo "changes" + - name: Commit & Push in ${{ env.GITHUB_REF_SLUG_URL }} + if: steps.git_status.outputs.result == 'changes' run: | git add . git config user.name "github-actions" diff --git a/.github/workflows/keywords-generator.yml b/.github/workflows/keywords-generator.yml new file mode 100644 index 0000000000..44ea5656f4 --- /dev/null +++ b/.github/workflows/keywords-generator.yml @@ -0,0 +1,57 @@ +name: Keywords autogenerated + +on: + workflow_dispatch: + pull_request: + branches: + - production + paths: + - "icons/**" + +jobs: + generate-keywords: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get branch name + uses: rlespinasse/github-slug-action@v3.x + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: "3.x" + + - name: Upgrade pip, setuptools, and wheel + run: | + pip install --upgrade pip setuptools wheel + + # Paso 3: Instalar dependencias de Python + - name: Install dependencies + run: | + pip install openai python-dotenv --use-pep517 + + - name: Install prettier + run: npm install -g prettier + + - name: Run keywords generator + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + working-directory: .github/keywords + run: python3 keywords-generator.py + + - name: Check for changes + id: git_status + run: | + git diff --exit-code || echo "changes" + + - name: Commit & Push in ${{ env.GITHUB_REF_SLUG_URL }} + if: steps.git_status.outputs.result == 'changes' + run: | + git add . + git config user.name "github-actions" + git config user.email "github-actions[bot]@users.noreply.github.com" + git commit -am "update changelog" + git push origin ${{ env.GITHUB_REF_SLUG_URL }} diff --git a/.gitignore b/.gitignore index abb3bcc5b8..0be9d97ab4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .AppleDouble .LSOverride *.idea +*.env # Icon must end with two Icon @@ -60,4 +61,5 @@ o2-new-filled.json #figma-export-icons o2-new-regular.json #figma-export-icons -o2-new-light.json \ No newline at end of file +o2-new-light.json + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b4426225f9..9274a319c2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,9 +5,8 @@ Mística-icons is built to grow, that means that If you need a new icon, you hav 1. Check If mistica-icons doesn't cover your need in [this list](https://github.com/Telefonica/mistica-icons/blob/production/README.md) 2. Read [Brand Factory](https://brandfactory.telefonica.com/hub/134) icons guidelines by brand 3. Create a new icon following the guidelines and **with 3 weights!** _(light / regular / filled)_ -4. Provide 3 synonyms for this icon. [Keywords file](icons/icons-keywords.json) -5. Create an issue [here](https://github.com/Telefonica/mistica-design/issues/new?assignees=&labels=fundamentals%3A+icons%2Crequest+%E2%9C%A8&template=icon_request.yml&title=Title) -6. That's all! We will review If your icon have all the needs to add it to mistica-icons +4. Create an issue [here](https://github.com/Telefonica/mistica-design/issues/new?assignees=&labels=fundamentals%3A+icons%2Crequest+%E2%9C%A8&template=icon_request.yml&title=Title) +5. That's all! We will review If your icon have all the needs to add it to mistica-icons # Report an icon bug diff --git a/icons/icons-keywords.json b/icons/icons-keywords.json index 145b9547df..1ead02bc95 100644 --- a/icons/icons-keywords.json +++ b/icons/icons-keywords.json @@ -174,8 +174,8 @@ "dartboard": ["darts target", "bullseye board", "throwing game", "tablero de dardos", "alvo de dardos", "Dartbrett"], "data": ["information", "facts", "data points", "datos", "informações", "Daten"], "data-10-gb": ["10 gigabytes of data", "data plan", "data allocation", "10 gigabytes de datos", "plano de dados", "10 Gigabyte Daten"], - "data-30-gb": ["30 gigabytes of data", "data plan", "data allocation", "30 gigabytes de datos", "plano de dados", "30 Gigabyte Daten"], "data-100-gb": ["100 gigabytes of data", "large data plan", "huge data allocation", "100 gigabytes de datos", "plano de datos grande", "100 Gigabyte Daten"], + "data-30-gb": ["30 gigabytes of data", "data plan", "data allocation", "30 gigabytes de datos", "plano de dados", "30 Gigabyte Daten"], "data-alert": ["data warning", "usage alert", "data notification", "advertencia de datos", "alerta de uso", "Datenbenachrichtigung"], "data-bonus": ["extra data", "bonus allocation", "additional data", "datos adicionales", "alocação de bônus", "zusätzliche Daten"], "data-centre": ["data center", "server farm", "information hub", "centro de datos", "centro de servidores", "Datenzentrum"],