Deleted everything
@@ -1,4 +0,0 @@
|
|||||||
TOKEN=YOUR DISCORD BOT TOKEN HERE
|
|
||||||
OPENAI=YOUR OPENAI API KEY HERE
|
|
||||||
USE_IMAGES=No
|
|
||||||
COOLDOWN=5
|
|
||||||
2
.gitattributes
vendored
@@ -1,2 +0,0 @@
|
|||||||
# Auto detect text files and perform LF normalization
|
|
||||||
* text=auto
|
|
||||||
156
.gitignore
vendored
@@ -1,156 +0,0 @@
|
|||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
*.py,cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
cover/
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
|
||||||
db.sqlite3-journal
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
.pybuilder/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
# For a library or package, you might want to ignore these files since the code is
|
|
||||||
# intended to run in multiple environments; otherwise, check them in:
|
|
||||||
# .python-version
|
|
||||||
|
|
||||||
# pipenv
|
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
||||||
# install all needed dependencies.
|
|
||||||
#Pipfile.lock
|
|
||||||
|
|
||||||
# poetry
|
|
||||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
||||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
||||||
# commonly ignored for libraries.
|
|
||||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
||||||
#poetry.lock
|
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
||||||
__pypackages__/
|
|
||||||
|
|
||||||
# Celery stuff
|
|
||||||
celerybeat-schedule
|
|
||||||
celerybeat.pid
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
||||||
|
|
||||||
# pytype static type analyzer
|
|
||||||
.pytype/
|
|
||||||
|
|
||||||
# Cython debug symbols
|
|
||||||
cython_debug/
|
|
||||||
|
|
||||||
# PyCharm
|
|
||||||
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
|
|
||||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
||||||
#.idea/
|
|
||||||
token.env
|
|
||||||
key.env
|
|
||||||
marp.exe
|
|
||||||
/data
|
|
||||||
21
LICENSE
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 Paillat
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
71
README.md
@@ -1,71 +0,0 @@
|
|||||||
# Presentator
|
|
||||||
A Discord bot that generates FULL powerpoints about a given subject thanks to openai's gpt3.
|
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/Paillat-dev/presentator/main/examples/steve-jobs/Steve-Jobs-1.png" width="600" >
|
|
||||||
<img src="https://raw.githubusercontent.com/Paillat-dev/presentator/main/examples/python/the-python-programming-language-1.png" width="600" >
|
|
||||||
|
|
||||||
|
|
||||||
# How it works
|
|
||||||
- The bot sends a request to the openai api with the given subject and indications in the marp markdown format
|
|
||||||
- We extract the images from the markdown and send them to the image generation api
|
|
||||||
- We generate the pdf and html files from the markdown
|
|
||||||
- We send the pdf and html files to the user
|
|
||||||
|
|
||||||
# How to install
|
|
||||||
**IMPORTANT** Linux and MacOS installation isn't documented yet, if anyone wanths to complete it, feel free to do a pull request.
|
|
||||||
## Requirements
|
|
||||||
- Python 3.8
|
|
||||||
- Pip
|
|
||||||
- A Discord bot token
|
|
||||||
- An openai api key
|
|
||||||
- (Optional) An Nvidia GPU (for local image generation)
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
- Clone the repository
|
|
||||||
- Install the requirements with
|
|
||||||
`pip install -r requirements.txt`
|
|
||||||
- Download the correct zip / tar marp file for your os [here](https://github.com/marp-team/marp-cli/releases/tag/v2.3.0).
|
|
||||||
- Extract the content of that file in the presentator folder (the one you downloaded on step 1).
|
|
||||||
- Restart your computer
|
|
||||||
- Put your openai api key and discord bot token in the `.env.example` file and rename it to `.env`
|
|
||||||
|
|
||||||
## Image generation (optional)
|
|
||||||
### With Stable Diffusion UI (powerful gpu option)
|
|
||||||
- Install [Stable Diffusion UI](https://github.com/cmdr2/stable-diffusion-ui) and switch to the `beta` branch.
|
|
||||||
- Copy the `./image_gen_api/main.py` file to the `stable-diffusion-ui` folder
|
|
||||||
- Open the file called `Dev Console.cmd` in the `stable-diffusion-ui` folder and run the following commands:
|
|
||||||
```
|
|
||||||
pip install uvicorn
|
|
||||||
pip install fastapi
|
|
||||||
```
|
|
||||||
- In the file `.env`, set the `USE_IMAGES` variable to `sd`
|
|
||||||
### With DALL·E 2 (costs dalle credits)
|
|
||||||
- In the file `.env`, set the `USE_IMAGES` variable to `dalle`
|
|
||||||
# Running
|
|
||||||
- Run the `main.py` file with :
|
|
||||||
```
|
|
||||||
python main.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Local image generation (optional, only if you use the local image generation option)
|
|
||||||
- Open the file called `Dev Console.cmd` in the `stable-diffusion-ui` folder and run the following commands:
|
|
||||||
```
|
|
||||||
uvicorn main:app --reload
|
|
||||||
```
|
|
||||||
|
|
||||||
# Commands
|
|
||||||
- `/present` : Generates a pdf presentation about the given subject
|
|
||||||
|
|
||||||
Options:
|
|
||||||
- `subject` : The subject of the presentation
|
|
||||||
- `language` : The language of the presentation (default: `english`)
|
|
||||||
- `style` : The style of the presentation (default: `default`)
|
|
||||||
- `indications` : Some more instructions about how the presentation should be generated (default: `None`)
|
|
||||||
- `/list` : Lists all of your presentations
|
|
||||||
- `/get` : Gets a presentation by its id another time
|
|
||||||
|
|
||||||
# Help
|
|
||||||
You can join our discord server if you need help
|
|
||||||
https://discord.gg/pB6hXtUeDv
|
|
||||||
|
|
||||||
Have fun!
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
presentator.paillat.dev
|
|
||||||
|
Before Width: | Height: | Size: 141 KiB |
|
Before Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 131 KiB |
@@ -1,6 +0,0 @@
|
|||||||
coarse-salt-in-a-wooden-bowl.png
|
|
||||||
ancient-roman-salting-factory-on-the-sea-shore.png
|
|
||||||
medieval-market-scene-with-salt-seller.png
|
|
||||||
salt-works-in-the-renaissance.png
|
|
||||||
industrial-salt-manufacturing-plant.png
|
|
||||||
modern-salt-factory-with-conveyor.png
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
---
|
|
||||||
marp: true
|
|
||||||
theme: ['default', 'gaia', 'uncover', 'default-dark', 'gaia-dark', 'uncover-dark']
|
|
||||||
class:
|
|
||||||
- lead
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Le sel (NaCl) à travers des âges
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Le sel est un composant essentiel de la vie sur terre et a été utilisé depuis des milliers d'années. Il a été utilisé pour la conservation des aliments, comme médicament, et aussi comme moyen de paiement. Dans cette présentation, nous allons explorer l'histoire et l'utilisation du sel à travers les âges et voir comment il s'est adapté et a évolué.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Antiquité
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Le sel était très important dans l'Antiquité. Les Romains payaient leurs soldats en sel, ce qui leur a donné le surnom de « sel ». Les anciens Égyptiens l'utilisaient pour conserver les aliments et le sel est même mentionné dans la Bible.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Moyen Âge
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Au Moyen Âge, le sel était considéré comme très précieux et était très cher. Il était utilisé pour la conservation des aliments et comme moyen de paiement. Les villes qui produisaient du sel ont prospéré et ont été fondées pour en profiter.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Renaissance
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Au cours de la Renaissance, le sel a continué à être utilisé pour conserver les aliments et comme moyen de paiement. Cependant, il a également été utilisé pour des applications médicales et comme source de minéraux pour le bétail.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Âge Industriel
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Avec l'avènement de l'âge industriel, la production de sel a été grandement améliorée et simplifiée. Des usines ont été construites et la production de sel a été industrialisée. Cela a permis une production en masse et un coût moins élevé.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## À l'ère moderne
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
À l'ère moderne, le sel est toujours important pour la conservation des aliments et pour d'autres usages. Cependant, il a également été utilisé pour des applications médicales et des usages industriels. Le sel est également utilisé pour le traitement des eaux usées et le nettoyage des surfaces.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
Le sel est un composant essentiel de la vie sur terre et a été utilisé depuis des milliers d'années. Il a été utilisé pour la conservation des aliments, comme médicament, et aussi comme moyen de paiement. Au cours des siècles, le sel a évolué et s'est adapté à de nouvelles utilisations à mesure que la technologie et la science progressaient. Il est maintenant utilisé pour de nombreux usages industriels, médicaux et domestiques.
|
|
||||||
|
Before Width: | Height: | Size: 557 KiB |
|
Before Width: | Height: | Size: 467 KiB |
|
Before Width: | Height: | Size: 365 KiB |
|
Before Width: | Height: | Size: 443 KiB |
|
Before Width: | Height: | Size: 449 KiB |
|
Before Width: | Height: | Size: 379 KiB |
|
Before Width: | Height: | Size: 453 KiB |
|
Before Width: | Height: | Size: 736 KiB |
|
Before Width: | Height: | Size: 265 KiB |
|
Before Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 232 KiB |
|
Before Width: | Height: | Size: 238 KiB |
|
Before Width: | Height: | Size: 213 KiB |
@@ -1,16 +0,0 @@
|
|||||||
import requests
|
|
||||||
import os
|
|
||||||
import openai
|
|
||||||
async def generate(prompt, path, mode, openai_key):
|
|
||||||
#r = requests.get(f"http://localhost:8000/generate_image?prompt={prompt}&path={path}")
|
|
||||||
if mode == "sd":
|
|
||||||
r = requests.get(f"http://localhost:8000/generate_image?prompt={prompt}&path={path}")
|
|
||||||
return "image generated"
|
|
||||||
if mode == "dalle":
|
|
||||||
openai.api_key = openai_key
|
|
||||||
img = await openai.Image.acreate(
|
|
||||||
prompt=prompt,
|
|
||||||
n=1,
|
|
||||||
size="512x512",
|
|
||||||
)
|
|
||||||
return img
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import sdkit
|
|
||||||
from sdkit.models import load_model
|
|
||||||
from sdkit.generate import generate_images
|
|
||||||
from sdkit.utils import save_images, log
|
|
||||||
from sdkit.filter import apply_filters
|
|
||||||
import os
|
|
||||||
from fastapi import FastAPI
|
|
||||||
#This is an API on the port 9009 that generates images from a prompt
|
|
||||||
#The prompt is the text that the model will use to generate the image
|
|
||||||
#The path is the path where the image will be saved
|
|
||||||
#The model is a model that generates images from text
|
|
||||||
|
|
||||||
path=""
|
|
||||||
prompt=""
|
|
||||||
app = FastAPI()
|
|
||||||
context = sdkit.Context()
|
|
||||||
context.model_paths['stable-diffusion'] = '.\\models\\stable-diffusion\\sd-v1-4.ckpt'
|
|
||||||
load_model(context, 'stable-diffusion')
|
|
||||||
context.model_paths['gfpgan'] = '.\\models\\gfpgan\\GFPGANv1.3.pth'
|
|
||||||
load_model(context, 'gfpgan')
|
|
||||||
print("Model loaded")
|
|
||||||
@app.get("/generate_image")
|
|
||||||
async def generate(prompt,path):
|
|
||||||
# set the path to the model file on the disk (.ckpt or .safetensors file)
|
|
||||||
print(f"Generating image for prompt: {prompt} and path: {path}")
|
|
||||||
# generate the image
|
|
||||||
image = generate_images(context, prompt=prompt, seed=42, width=512, height=512)
|
|
||||||
image_face_fixed = apply_filters(context, 'gfpgan', image)
|
|
||||||
# save the image
|
|
||||||
save_images(image_face_fixed, dir_path=path, file_name=prompt, output_format='png')
|
|
||||||
|
|
||||||
log.info("Generated images!")
|
|
||||||
221
main.py
@@ -1,221 +0,0 @@
|
|||||||
import openai
|
|
||||||
import discord
|
|
||||||
from discord import Intents
|
|
||||||
from discord.commands import slash_command, option
|
|
||||||
from discord.ext import commands
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import asyncio
|
|
||||||
import logging
|
|
||||||
import datetime
|
|
||||||
import base64
|
|
||||||
import requests
|
|
||||||
import zipfile
|
|
||||||
from zipfile import ZipFile
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
load_dotenv()
|
|
||||||
use_images = os.getenv("USE_IMAGES")
|
|
||||||
cooldown = os.getenv("COOLDOWN")
|
|
||||||
if use_images != "No": import imagesGeneration
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
imageint = ""
|
|
||||||
if use_images != "No": imageint = "To add an image illustration , use  at the beginning of the slide, just after \"---\". Use only .png. It's not possible to add technical images but only illustrations. The images are generated by an ai, the name of the file should be a detailed quite long description of the image wanted. You always need to specify the description of the image."
|
|
||||||
intstructions = f'''Here is a presentation with marp. It's not possible to make slides longer than 200 characters. to separate slides,
|
|
||||||
"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
"
|
|
||||||
then go at the line. The presentatio should be for everybody, all technical words and concepts, explained. {imageint} The presentation is minimum 20 slides long. You can use bulletpoints. Use markdown formatting (titles, etc...). The presentation has also a conclusion.'''
|
|
||||||
bot = discord.Bot()
|
|
||||||
|
|
||||||
styles = ["default", "gaia", "uncover", "default-dark", "gaia-dark", "uncover-dark", "olive"]
|
|
||||||
languages = ["english", "french", "spanish", "german", "italian", "portuguese", "russian", "chinese", "japanese", "korean", "arabic"]
|
|
||||||
darkstyles = ["default-dark", "gaia-dark", "uncover-dark"]
|
|
||||||
customstyles = ["olive"]
|
|
||||||
async def get_style(ctx: discord.AutocompleteContext):
|
|
||||||
"""Returns a list of colors that begin with the characters entered so far."""
|
|
||||||
return [style for style in styles if style.startswith(ctx.value.lower())]
|
|
||||||
async def get_ln(ctx: discord.AutocompleteContext):
|
|
||||||
return [language for language in languages if language.startswith(ctx.value.lower())]
|
|
||||||
|
|
||||||
@bot.slash_command(name="private_present", description="Generate a presentation with marp, private command for user 707196665668436019")
|
|
||||||
@option(name="subject", description="The subject of the presentation", required=True)
|
|
||||||
@option(name="style", description="The style of the presentation", required=False, autocomplete=get_style)
|
|
||||||
@option(name="center", description="Center the text", required=False)
|
|
||||||
@option(name="language", description="The language of the presentation", required=False, autocomplete=get_ln)
|
|
||||||
@option(name="indications", description="The indications for the presentation", required=False)
|
|
||||||
#command wprks only in dm and only for user 707196665668436019
|
|
||||||
@commands.is_owner()
|
|
||||||
async def private_present(ctx: discord.ApplicationContext, subject: str, style: str = "default", center: bool = True, language: str = "english", indications: str = ""):
|
|
||||||
await present(ctx, subject, style, language, indications)
|
|
||||||
|
|
||||||
@bot.slash_command(name="present", description="Generate a presentation with marp")
|
|
||||||
#we create a function that takes the subject of the presentation and the style of the presentation as arguments, and that
|
|
||||||
@option(name="subject", description="The subject of the presentation", required=True)
|
|
||||||
@option(name="style", description="The style of the presentation", required=False, autocomplete=get_style)
|
|
||||||
@option(name="center", description="Center the text", required=False)
|
|
||||||
@option(name="language", description="The language of the presentation", required=False, autocomplete=get_ln)
|
|
||||||
@option(name="indications", description="The indications for the presentation", required=False)
|
|
||||||
# a cooldown of duration cooldown seconds, except if the user is 707196665668436019
|
|
||||||
#@commands.cooldown(1, int(cooldown), commands.BucketType.user)
|
|
||||||
@commands.cooldown(1, int(cooldown), commands.BucketType.guild)
|
|
||||||
async def normal_present(ctx: discord.ApplicationContext, subject: str, style: str = "default", center: bool = True, language: str = "english", indications: str = ""):
|
|
||||||
await present(ctx, subject, style, language, indications)
|
|
||||||
async def present(ctx: discord.ApplicationContext, subject: str, style: str = "default", center: bool = True, language: str = "english", indications: str = ""):
|
|
||||||
await ctx.defer()
|
|
||||||
date = datetime.datetime.now()
|
|
||||||
date = date.strftime("%Y-%m-%d-%H-%M-%S")
|
|
||||||
#if the style is dark
|
|
||||||
dark = False
|
|
||||||
if style in darkstyles:
|
|
||||||
style = style.replace("-dark", "")
|
|
||||||
dark = True
|
|
||||||
marp = f'''---
|
|
||||||
marp: true
|
|
||||||
theme: {styles[styles.index(style)]}
|
|
||||||
class:
|
|
||||||
'''
|
|
||||||
if dark: marp = marp + f" - invert\n---"
|
|
||||||
if center: marp = marp + " - lead\n---"
|
|
||||||
else: marp = marp + "\n---"
|
|
||||||
# if style in customstyles:
|
|
||||||
# marp = f"/* @theme {style} */\n" + marp
|
|
||||||
# print(marp)
|
|
||||||
prompt = f"{intstructions} {indications} The subject of the presentation is: {subject} The Language is: {language} <|endofprompt|> \n {marp}"
|
|
||||||
subject2 = subject
|
|
||||||
forbidden = ["\\", "/", "?", "!", ":", ";", "(", ")", "[", "]", "{", "}", "'", '"', "=", "+", "*", "&", "^", "%", "$", "#", "@", "`", "~", "|", "<", ">", ",", ".", "?", " "]
|
|
||||||
for i in forbidden:
|
|
||||||
if i in subject: subject = subject.replace(i, "-")
|
|
||||||
#we save teh subject in base64 in a variable
|
|
||||||
#if dosen't exist, create a directory called "userid" where the userid is the id of the user who called the command
|
|
||||||
uid = str(ctx.author.id)
|
|
||||||
if not os.path.exists("./data/"+uid):
|
|
||||||
os.mkdir("./data/"+uid)
|
|
||||||
datenow = datetime.datetime.now()
|
|
||||||
datenow = datenow.strftime("%Y-%m-%d-%H-%M-%S")
|
|
||||||
response = await openai.Completion.acreate(
|
|
||||||
engine="text-davinci-003",
|
|
||||||
prompt=prompt,
|
|
||||||
temperature=0.6,
|
|
||||||
max_tokens=1024,
|
|
||||||
top_p=1,
|
|
||||||
frequency_penalty=0,
|
|
||||||
presence_penalty=0,
|
|
||||||
stop=["<|endofprompt|>"]
|
|
||||||
)
|
|
||||||
#we save the output in a variable
|
|
||||||
output = response["choices"][0]["text"]
|
|
||||||
present = marp + output
|
|
||||||
##we save the output in a file called "subject.md"
|
|
||||||
matches = re.finditer(r'!\[.*?\]\((.*?)\)', present)
|
|
||||||
image_filenames = []
|
|
||||||
for match in matches:
|
|
||||||
image_filenames.append(match.group(1))
|
|
||||||
#we create a text file with the image names and a md file for the presentation with utf8 encoding
|
|
||||||
if len(subject) > 15: subject = subject[:15]
|
|
||||||
b64 = base64.urlsafe_b64encode(subject.encode("utf-8"))
|
|
||||||
os.mkdir(f"./data/{uid}/{b64}{datenow}")
|
|
||||||
path = f"./data/{uid}/{b64}{datenow}"
|
|
||||||
with open(f"{path}/{subject}-images.txt", "w", encoding="utf8") as f:
|
|
||||||
for image in image_filenames:
|
|
||||||
f.write(image + "\n")
|
|
||||||
with open(f"{path}/{subject}.md", "w", encoding="utf8") as f: f.write(present)
|
|
||||||
if len(image_filenames) > 0 and use_images!="no":
|
|
||||||
#now we first remove the extension from the image filenames by removing the last 4 characters
|
|
||||||
image_filenames = [image[:-4] for image in image_filenames]
|
|
||||||
print(image_filenames)
|
|
||||||
for images in image_filenames:
|
|
||||||
print ("generating image " + images + "with " + str(use_images))
|
|
||||||
r = await imagesGeneration.generate(images, f"{os.getcwd()}\\data\\{uid}\\{b64}{datenow}\\", str(use_images), apikey)
|
|
||||||
if str(use_images) == "sd": os.rename(f"{os.getcwd()}\\.\\data\\{uid}\\{b64}{datenow}\\{images}_0.png", f"{os.getcwd()}\\data\\{uid}\\{b64}{datenow}\\{images}.png")
|
|
||||||
if str(use_images) == "dalle":
|
|
||||||
image_url = r['data'][0]['url']
|
|
||||||
img_data = requests.get(image_url).content
|
|
||||||
with open(f'{path}/{images}.png', 'wb') as handler:
|
|
||||||
handler.write(img_data)
|
|
||||||
await asyncio.sleep(15) #wait 15 seconds to avoid rate limiting
|
|
||||||
cmd = f"--pdf --allow-local-files {path}/{subject}.md"
|
|
||||||
if style in customstyles: cmd = cmd + f" --theme ./themes/{style}.css"
|
|
||||||
if os.path.exists("./marp.exe"):
|
|
||||||
os.system(f"marp.exe {cmd}")
|
|
||||||
else:
|
|
||||||
cmd = cmd.replace("'", "\\'")
|
|
||||||
os.system(f"./marp {cmd}")
|
|
||||||
cmd = f" --image png -o {path}/{subject}.png --allow-local-files {path}/{subject}.md"
|
|
||||||
if style in customstyles: cmd = cmd + f" --theme ./themes/{style}.css"
|
|
||||||
if os.path.exists("./marp.exe"):
|
|
||||||
os.system(f"marp.exe {cmd}")
|
|
||||||
else:
|
|
||||||
cmd = cmd.replace("'", "\\'")
|
|
||||||
os.system(f"./marp {cmd}")
|
|
||||||
cmd = f" --html --allow-local-files {path}/{subject}.md"
|
|
||||||
if style in customstyles: cmd = cmd + f" --theme ./themes/{style}.css"
|
|
||||||
if os.path.exists("./marp.exe"):
|
|
||||||
os.system(f"marp.exe {cmd}")
|
|
||||||
else:
|
|
||||||
cmd = cmd.replace("'", "\\'")
|
|
||||||
os.system(f"./marp {cmd}")
|
|
||||||
cmd = f" --pptx --allow-local-files {path}/{subject}.md"
|
|
||||||
if style in customstyles: cmd = cmd + f" --theme ./themes/{style}.css"
|
|
||||||
if os.path.exists("./marp.exe"):
|
|
||||||
os.system(f"marp.exe {cmd}")
|
|
||||||
else:
|
|
||||||
cmd = cmd.replace("'", "\\'")
|
|
||||||
os.system(f"./marp {cmd}")
|
|
||||||
#now, we create a zip file with all the files
|
|
||||||
zipObj = ZipFile(f"{path}/{subject}.zip", 'w')
|
|
||||||
zipObj.write(f"{path}/{subject}.md", f"{subject}.md")
|
|
||||||
zipObj.write(f"{path}/{subject}.html", f"{subject}.html")
|
|
||||||
zipObj.write(f"{path}/{subject}.pdf", f"{subject}.pdf")
|
|
||||||
zipObj.write(f"{path}/{subject}.png", f"{subject}.png")
|
|
||||||
zipObj.write(f"{path}/{subject}.pptx", f"{subject}.pptx")
|
|
||||||
with open(f"{path}/{subject}-images.txt", "r", encoding="utf8") as f:
|
|
||||||
for image in f.readlines():
|
|
||||||
zipObj.write(f"{path}/{image.strip()}", f"{image.strip()}")
|
|
||||||
zipObj.close()
|
|
||||||
embed = discord.Embed(title=subject2, description="Thanks for using presentator bot. You will find your presentation in the attached zip file in the following formats: markdown, html, pdf, pptx, and the presentation' images. If you want to modify your presentation you can use the markdown file. More information about how to modify the file [HERE](https://marp.app).", color=discord.Color.brand_red())
|
|
||||||
files = [discord.File(f"{path}/{subject}.zip"), discord.File(f"{path}/{subject}.png")]
|
|
||||||
embed.set_image(url=f"attachment://{subject}.png")
|
|
||||||
await ctx.respond(embed=embed, files=files)
|
|
||||||
|
|
||||||
@bot.slash_command(name="list", description="List all the presentations you have created")
|
|
||||||
async def list(ctx: discord.ApplicationContext):
|
|
||||||
embed = discord.Embed(title="Presentations", description="Here is the list of all the presentations you have created. You can download the presentation in different formats (pdf, markdown, html) by doing `/get` \"*presentation id*\". The images are generated by an ai. If you want to modify your presentation you can use the markdown file. More information about how to modify the file [HERE](https://marp.app).", color=0x00ff00)
|
|
||||||
liste = await get_presentations(str(ctx.author.id))
|
|
||||||
for key in liste:
|
|
||||||
embed.add_field(name=f"{liste[key]}", value=f"</get:1063051827010084925> `{key}`", inline=False)
|
|
||||||
await ctx.respond(embed=embed, ephemeral=True)
|
|
||||||
|
|
||||||
async def get_presentations(uid):
|
|
||||||
folders = os.listdir(f"./data/{uid}")
|
|
||||||
names = {}
|
|
||||||
for folder in folders:
|
|
||||||
name = base64.urlsafe_b64decode(folder[2:-20]).decode("utf-8")
|
|
||||||
names[folder] = name
|
|
||||||
return names
|
|
||||||
|
|
||||||
@bot.slash_command(name="get", description="Get a presentation")
|
|
||||||
@option(name="pid", description="The id of the presentation", required=True)
|
|
||||||
async def get(ctx: discord.ApplicationContext, pid: str):
|
|
||||||
uid = str(ctx.author.id)
|
|
||||||
liste = await get_presentations(uid)
|
|
||||||
if pid in liste:
|
|
||||||
files = [discord.File(f"./data/{uid}/{pid}/{liste[pid]}.pdf"), discord.File(f"./data/{uid}/{pid}/{liste[pid]}.md"), discord.File(f"./data/{uid}/{pid}/{liste[pid]}.html")]
|
|
||||||
await ctx.respond(files=files, ephemeral=True)
|
|
||||||
|
|
||||||
@bot.event
|
|
||||||
async def on_ready():
|
|
||||||
print("Bot is ready")
|
|
||||||
if not os.path.exists("data"):
|
|
||||||
os.mkdir("data")
|
|
||||||
@bot.event
|
|
||||||
async def on_application_command_error(ctx, error):
|
|
||||||
#if there is an error we send a message to the user
|
|
||||||
await ctx.respond(f"An error occured: {error}", ephemeral=True)
|
|
||||||
|
|
||||||
#get the openai key drom he key.env file
|
|
||||||
token = os.getenv("TOKEN")
|
|
||||||
apikey = os.getenv("OPENAI")
|
|
||||||
openai.api_key = apikey
|
|
||||||
bot.run(token)
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
openai
|
|
||||||
py-cord
|
|
||||||
python-dotenv
|
|
||||||
465
themes/olive.css
@@ -1,465 +0,0 @@
|
|||||||
@charset "UTF-8";
|
|
||||||
/*!
|
|
||||||
* Marp / Marpit Olive theme.
|
|
||||||
*
|
|
||||||
* @theme olive
|
|
||||||
* @author MATSUBARA Nobutada
|
|
||||||
* @size 4:3 960px 720px
|
|
||||||
* @size 16:9 1280px 720px
|
|
||||||
*/
|
|
||||||
@import url("https://fonts.googleapis.com/css?family=Lato:400,900|Roboto+Mono:400,700");
|
|
||||||
@import url("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.8/styles/github.min.css");
|
|
||||||
svg[data-marp-fitting='svg'] {
|
|
||||||
max-height: 580px; }
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
margin: 0.5em 0 0 0; }
|
|
||||||
h1 strong,
|
|
||||||
h2 strong,
|
|
||||||
h3 strong,
|
|
||||||
h4 strong,
|
|
||||||
h5 strong,
|
|
||||||
h6 strong {
|
|
||||||
font-weight: inherit; }
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 1.8em; }
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 1.5em; }
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 1.3em; }
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: 1.1em; }
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 1em; }
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: 0.9em; }
|
|
||||||
|
|
||||||
p,
|
|
||||||
blockquote {
|
|
||||||
margin: 1em 0 0 0; }
|
|
||||||
|
|
||||||
ul > li,
|
|
||||||
ol > li {
|
|
||||||
margin: 0.3em 0 0 0; }
|
|
||||||
ul > li > p,
|
|
||||||
ol > li > p {
|
|
||||||
margin: 0.6em 0 0 0; }
|
|
||||||
|
|
||||||
code {
|
|
||||||
display: inline-block;
|
|
||||||
font-family: 'NasuM', 'Roboto Mono', monospace;
|
|
||||||
font-size: 0.8em;
|
|
||||||
letter-spacing: 0;
|
|
||||||
margin: -0.1em 0.15em;
|
|
||||||
padding: 0.1em 0.2em;
|
|
||||||
vertical-align: baseline; }
|
|
||||||
|
|
||||||
pre {
|
|
||||||
display: block;
|
|
||||||
margin: 1em 0 0 0;
|
|
||||||
min-height: 1em;
|
|
||||||
overflow: visible; }
|
|
||||||
pre code {
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 0;
|
|
||||||
min-width: 100%;
|
|
||||||
padding: 0.5em;
|
|
||||||
font-size: 0.7em; }
|
|
||||||
pre code svg[data-marp-fitting='svg'] {
|
|
||||||
max-height: calc(580px - 1em); }
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
margin: 1em 0 0 0;
|
|
||||||
padding: 0 1em;
|
|
||||||
position: relative; }
|
|
||||||
blockquote::after, blockquote::before {
|
|
||||||
content: '“';
|
|
||||||
display: block;
|
|
||||||
font-family: 'Times New Roman', serif;
|
|
||||||
font-weight: bold;
|
|
||||||
position: absolute; }
|
|
||||||
blockquote::before {
|
|
||||||
top: 0;
|
|
||||||
left: 0; }
|
|
||||||
blockquote::after {
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
transform: rotate(180deg); }
|
|
||||||
blockquote > *:first-child {
|
|
||||||
margin-top: 0; }
|
|
||||||
|
|
||||||
mark {
|
|
||||||
background: transparent; }
|
|
||||||
|
|
||||||
table {
|
|
||||||
border-spacing: 0;
|
|
||||||
border-collapse: collapse;
|
|
||||||
margin: 1em 0 0 0; }
|
|
||||||
table th,
|
|
||||||
table td {
|
|
||||||
padding: 0.2em 0.4em;
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid; }
|
|
||||||
|
|
||||||
section {
|
|
||||||
background-image: linear-gradient(135deg, rgba(136, 136, 136, 0), rgba(136, 136, 136, 0.02) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0.05));
|
|
||||||
font-size: 28px;
|
|
||||||
font-family: '源真ゴシック', 'ヒラギノ角ゴ Pro W3', 'Lato', 'Avenir Next', 'Avenir', 'Trebuchet MS', 'Segoe UI', sans-serif;
|
|
||||||
line-height: 1.35;
|
|
||||||
letter-spacing: 1.25px;
|
|
||||||
padding: 70px;
|
|
||||||
color: #FFF2DD;
|
|
||||||
background-color: #4e4f53; }
|
|
||||||
section > *:first-child,
|
|
||||||
section > header:first-child + * {
|
|
||||||
margin-top: 0; }
|
|
||||||
section a,
|
|
||||||
section mark {
|
|
||||||
color: #CCA551; }
|
|
||||||
section code {
|
|
||||||
background: #dcd1c1;
|
|
||||||
color: #4e4f53; }
|
|
||||||
section h1 strong,
|
|
||||||
section h2 strong,
|
|
||||||
section h3 strong,
|
|
||||||
section h4 strong,
|
|
||||||
section h5 strong,
|
|
||||||
section h6 strong {
|
|
||||||
color: #CCA551; }
|
|
||||||
section h1 img,
|
|
||||||
section h2 img,
|
|
||||||
section h3 img,
|
|
||||||
section h4 img,
|
|
||||||
section h5 img,
|
|
||||||
section h6 img {
|
|
||||||
display: block;
|
|
||||||
margin: auto; }
|
|
||||||
section pre > code {
|
|
||||||
background: #FFF2DD; }
|
|
||||||
section header,
|
|
||||||
section footer,
|
|
||||||
section section::after,
|
|
||||||
section blockquote::before,
|
|
||||||
section blockquote::after {
|
|
||||||
color: #dcd1c1; }
|
|
||||||
section table th,
|
|
||||||
section table td {
|
|
||||||
border-color: #FFF2DD; }
|
|
||||||
section table thead th {
|
|
||||||
background: #FFF2DD;
|
|
||||||
color: #4e4f53; }
|
|
||||||
section table tbody > tr:nth-child(odd) td,
|
|
||||||
section table tbody > tr:nth-child(odd) th {
|
|
||||||
background: rgba(255, 242, 221, 0.1); }
|
|
||||||
section.invert {
|
|
||||||
color: #4e4f53;
|
|
||||||
background-color: #FFF2DD; }
|
|
||||||
section.invert a,
|
|
||||||
section.invert mark {
|
|
||||||
color: #CCA551; }
|
|
||||||
section.invert code {
|
|
||||||
background: #71706f;
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.invert h1 strong,
|
|
||||||
section.invert h2 strong,
|
|
||||||
section.invert h3 strong,
|
|
||||||
section.invert h4 strong,
|
|
||||||
section.invert h5 strong,
|
|
||||||
section.invert h6 strong {
|
|
||||||
color: #CCA551; }
|
|
||||||
section.invert h1 img,
|
|
||||||
section.invert h2 img,
|
|
||||||
section.invert h3 img,
|
|
||||||
section.invert h4 img,
|
|
||||||
section.invert h5 img,
|
|
||||||
section.invert h6 img {
|
|
||||||
display: block;
|
|
||||||
margin: auto; }
|
|
||||||
section.invert pre > code {
|
|
||||||
background: #4e4f53; }
|
|
||||||
section.invert header,
|
|
||||||
section.invert footer,
|
|
||||||
section.invert section::after,
|
|
||||||
section.invert blockquote::before,
|
|
||||||
section.invert blockquote::after {
|
|
||||||
color: #71706f; }
|
|
||||||
section.invert table th,
|
|
||||||
section.invert table td {
|
|
||||||
border-color: #4e4f53; }
|
|
||||||
section.invert table thead th {
|
|
||||||
background: #4e4f53;
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.invert table tbody > tr:nth-child(odd) td,
|
|
||||||
section.invert table tbody > tr:nth-child(odd) th {
|
|
||||||
background: rgba(78, 79, 83, 0.1); }
|
|
||||||
section.olive {
|
|
||||||
color: #4e4f53;
|
|
||||||
background-color: #CCA551; }
|
|
||||||
section.olive a,
|
|
||||||
section.olive mark {
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.olive code {
|
|
||||||
background: #676053;
|
|
||||||
color: #CCA551; }
|
|
||||||
section.olive h1 strong,
|
|
||||||
section.olive h2 strong,
|
|
||||||
section.olive h3 strong,
|
|
||||||
section.olive h4 strong,
|
|
||||||
section.olive h5 strong,
|
|
||||||
section.olive h6 strong {
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.olive h1 img,
|
|
||||||
section.olive h2 img,
|
|
||||||
section.olive h3 img,
|
|
||||||
section.olive h4 img,
|
|
||||||
section.olive h5 img,
|
|
||||||
section.olive h6 img {
|
|
||||||
display: block;
|
|
||||||
margin: auto; }
|
|
||||||
section.olive pre > code {
|
|
||||||
background: #4e4f53; }
|
|
||||||
section.olive header,
|
|
||||||
section.olive footer,
|
|
||||||
section.olive section::after,
|
|
||||||
section.olive blockquote::before,
|
|
||||||
section.olive blockquote::after {
|
|
||||||
color: #676053; }
|
|
||||||
section.olive table th,
|
|
||||||
section.olive table td {
|
|
||||||
border-color: #4e4f53; }
|
|
||||||
section.olive table thead th {
|
|
||||||
background: #4e4f53;
|
|
||||||
color: #CCA551; }
|
|
||||||
section.olive table tbody > tr:nth-child(odd) td,
|
|
||||||
section.olive table tbody > tr:nth-child(odd) th {
|
|
||||||
background: rgba(78, 79, 83, 0.1); }
|
|
||||||
section.lead {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
justify-content: center; }
|
|
||||||
section.lead h1,
|
|
||||||
section.lead h2,
|
|
||||||
section.lead h3,
|
|
||||||
section.lead h4,
|
|
||||||
section.lead h5,
|
|
||||||
section.lead h6 {
|
|
||||||
text-align: center; }
|
|
||||||
section.lead h1 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead h2 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead h3 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead h4 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead h5 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead h6 svg[data-marp-fitting='svg'] {
|
|
||||||
--preserve-aspect-ratio: xMidYMid meet; }
|
|
||||||
section.lead p {
|
|
||||||
text-align: center; }
|
|
||||||
section.lead blockquote > h1,
|
|
||||||
section.lead blockquote > h2,
|
|
||||||
section.lead blockquote > h3,
|
|
||||||
section.lead blockquote > h4,
|
|
||||||
section.lead blockquote > h5,
|
|
||||||
section.lead blockquote > h6,
|
|
||||||
section.lead blockquote > p {
|
|
||||||
text-align: left; }
|
|
||||||
section.lead blockquote svg[data-marp-fitting='svg']:not([data-marp-fitting-math]) {
|
|
||||||
--preserve-aspect-ratio: xMinYMin meet; }
|
|
||||||
section.lead ul > li > p,
|
|
||||||
section.lead ol > li > p {
|
|
||||||
text-align: left; }
|
|
||||||
section.lead table {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto; }
|
|
||||||
section.lead-invert {
|
|
||||||
color: #4e4f53;
|
|
||||||
background-color: #FFF2DD;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
justify-content: center; }
|
|
||||||
section.lead-invert a,
|
|
||||||
section.lead-invert mark {
|
|
||||||
color: #CCA551; }
|
|
||||||
section.lead-invert code {
|
|
||||||
background: #71706f;
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.lead-invert h1 strong,
|
|
||||||
section.lead-invert h2 strong,
|
|
||||||
section.lead-invert h3 strong,
|
|
||||||
section.lead-invert h4 strong,
|
|
||||||
section.lead-invert h5 strong,
|
|
||||||
section.lead-invert h6 strong {
|
|
||||||
color: #CCA551; }
|
|
||||||
section.lead-invert h1 img,
|
|
||||||
section.lead-invert h2 img,
|
|
||||||
section.lead-invert h3 img,
|
|
||||||
section.lead-invert h4 img,
|
|
||||||
section.lead-invert h5 img,
|
|
||||||
section.lead-invert h6 img {
|
|
||||||
display: block;
|
|
||||||
margin: auto; }
|
|
||||||
section.lead-invert pre > code {
|
|
||||||
background: #4e4f53; }
|
|
||||||
section.lead-invert header,
|
|
||||||
section.lead-invert footer,
|
|
||||||
section.lead-invert section::after,
|
|
||||||
section.lead-invert blockquote::before,
|
|
||||||
section.lead-invert blockquote::after {
|
|
||||||
color: #71706f; }
|
|
||||||
section.lead-invert table th,
|
|
||||||
section.lead-invert table td {
|
|
||||||
border-color: #4e4f53; }
|
|
||||||
section.lead-invert table thead th {
|
|
||||||
background: #4e4f53;
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.lead-invert table tbody > tr:nth-child(odd) td,
|
|
||||||
section.lead-invert table tbody > tr:nth-child(odd) th {
|
|
||||||
background: rgba(78, 79, 83, 0.1); }
|
|
||||||
section.lead-invert h1,
|
|
||||||
section.lead-invert h2,
|
|
||||||
section.lead-invert h3,
|
|
||||||
section.lead-invert h4,
|
|
||||||
section.lead-invert h5,
|
|
||||||
section.lead-invert h6 {
|
|
||||||
text-align: center; }
|
|
||||||
section.lead-invert h1 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-invert h2 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-invert h3 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-invert h4 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-invert h5 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-invert h6 svg[data-marp-fitting='svg'] {
|
|
||||||
--preserve-aspect-ratio: xMidYMid meet; }
|
|
||||||
section.lead-invert p {
|
|
||||||
text-align: center; }
|
|
||||||
section.lead-invert blockquote > h1,
|
|
||||||
section.lead-invert blockquote > h2,
|
|
||||||
section.lead-invert blockquote > h3,
|
|
||||||
section.lead-invert blockquote > h4,
|
|
||||||
section.lead-invert blockquote > h5,
|
|
||||||
section.lead-invert blockquote > h6,
|
|
||||||
section.lead-invert blockquote > p {
|
|
||||||
text-align: left; }
|
|
||||||
section.lead-invert blockquote svg[data-marp-fitting='svg']:not([data-marp-fitting-math]) {
|
|
||||||
--preserve-aspect-ratio: xMinYMin meet; }
|
|
||||||
section.lead-invert ul > li > p,
|
|
||||||
section.lead-invert ol > li > p {
|
|
||||||
text-align: left; }
|
|
||||||
section.lead-invert table {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto; }
|
|
||||||
section.lead-olive {
|
|
||||||
color: #4e4f53;
|
|
||||||
background-color: #CCA551;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
justify-content: center; }
|
|
||||||
section.lead-olive a,
|
|
||||||
section.lead-olive mark {
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.lead-olive code {
|
|
||||||
background: #676053;
|
|
||||||
color: #CCA551; }
|
|
||||||
section.lead-olive h1 strong,
|
|
||||||
section.lead-olive h2 strong,
|
|
||||||
section.lead-olive h3 strong,
|
|
||||||
section.lead-olive h4 strong,
|
|
||||||
section.lead-olive h5 strong,
|
|
||||||
section.lead-olive h6 strong {
|
|
||||||
color: #FFF2DD; }
|
|
||||||
section.lead-olive h1 img,
|
|
||||||
section.lead-olive h2 img,
|
|
||||||
section.lead-olive h3 img,
|
|
||||||
section.lead-olive h4 img,
|
|
||||||
section.lead-olive h5 img,
|
|
||||||
section.lead-olive h6 img {
|
|
||||||
display: block;
|
|
||||||
margin: auto; }
|
|
||||||
section.lead-olive pre > code {
|
|
||||||
background: #4e4f53; }
|
|
||||||
section.lead-olive header,
|
|
||||||
section.lead-olive footer,
|
|
||||||
section.lead-olive section::after,
|
|
||||||
section.lead-olive blockquote::before,
|
|
||||||
section.lead-olive blockquote::after {
|
|
||||||
color: #676053; }
|
|
||||||
section.lead-olive table th,
|
|
||||||
section.lead-olive table td {
|
|
||||||
border-color: #4e4f53; }
|
|
||||||
section.lead-olive table thead th {
|
|
||||||
background: #4e4f53;
|
|
||||||
color: #CCA551; }
|
|
||||||
section.lead-olive table tbody > tr:nth-child(odd) td,
|
|
||||||
section.lead-olive table tbody > tr:nth-child(odd) th {
|
|
||||||
background: rgba(78, 79, 83, 0.1); }
|
|
||||||
section.lead-olive h1,
|
|
||||||
section.lead-olive h2,
|
|
||||||
section.lead-olive h3,
|
|
||||||
section.lead-olive h4,
|
|
||||||
section.lead-olive h5,
|
|
||||||
section.lead-olive h6 {
|
|
||||||
text-align: center; }
|
|
||||||
section.lead-olive h1 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-olive h2 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-olive h3 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-olive h4 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-olive h5 svg[data-marp-fitting='svg'],
|
|
||||||
section.lead-olive h6 svg[data-marp-fitting='svg'] {
|
|
||||||
--preserve-aspect-ratio: xMidYMid meet; }
|
|
||||||
section.lead-olive p {
|
|
||||||
text-align: center; }
|
|
||||||
section.lead-olive blockquote > h1,
|
|
||||||
section.lead-olive blockquote > h2,
|
|
||||||
section.lead-olive blockquote > h3,
|
|
||||||
section.lead-olive blockquote > h4,
|
|
||||||
section.lead-olive blockquote > h5,
|
|
||||||
section.lead-olive blockquote > h6,
|
|
||||||
section.lead-olive blockquote > p {
|
|
||||||
text-align: left; }
|
|
||||||
section.lead-olive blockquote svg[data-marp-fitting='svg']:not([data-marp-fitting-math]) {
|
|
||||||
--preserve-aspect-ratio: xMinYMin meet; }
|
|
||||||
section.lead-olive ul > li > p,
|
|
||||||
section.lead-olive ol > li > p {
|
|
||||||
text-align: left; }
|
|
||||||
section.lead-olive table {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto; }
|
|
||||||
|
|
||||||
header,
|
|
||||||
footer,
|
|
||||||
section::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 66%;
|
|
||||||
height: 70px;
|
|
||||||
line-height: 50px;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 10px 25px;
|
|
||||||
position: absolute; }
|
|
||||||
|
|
||||||
header {
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0; }
|
|
||||||
|
|
||||||
footer {
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0; }
|
|
||||||
|
|
||||||
section::after {
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
font-size: 80%; }
|
|
||||||
|
|
||||||
/*# sourceMappingURL=olive.css.map */
|
|
||||||