update of docs
This commit is contained in:
@@ -0,0 +1,164 @@
|
|||||||
|
# Meme-Otron guide
|
||||||
|
|
||||||
|
* [Commands](#commands)
|
||||||
|
* [Simple use](#simple-use)
|
||||||
|
* [Advanced use](#advanced-use)
|
||||||
|
* [Discord features](#discord-features)
|
||||||
|
* [CLI features](#cli-features)
|
||||||
|
* [List of templates](#list-of-templates)
|
||||||
|
* [Standard Templates](#standard-templates)
|
||||||
|
* [Reactions (no text)](#reactions-no-text)
|
||||||
|
* [Examples](#examples)
|
||||||
|
* [Example 1: Simple template](#example-1-simple-template)
|
||||||
|
* [Example 2: Use of empty texts](#example-2-use-of-empty-texts)
|
||||||
|
* [Example 3: Text + Template](#example-3-text--template)
|
||||||
|
* [Example 4: Complex composition](#example-4-complex-composition)
|
||||||
|
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### Simple use
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
You can generate memes by using the following arguments:
|
||||||
|
|
||||||
|
```
|
||||||
|
[meme id] "text1" "text2" ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Depending of the number of `"text"` arguments, several behavior occurs:
|
||||||
|
* **None**: you get the template that gives you the locations of texts. (see below)
|
||||||
|
* **Less than the template's**: the remaining texts are blank on the output
|
||||||
|
* **More than the template's**: the extra arguments are ignored
|
||||||
|
|
||||||
|
> Notes
|
||||||
|
> * You don't have to use all texts shown on the templates
|
||||||
|
> * You can use an empty text argument ( `""` ) to skip a text and keep it blank
|
||||||
|
|
||||||
|
See [Examples](#examples) to get an idea of how to use it.
|
||||||
|
|
||||||
|
### Advanced use
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
Since version 1.3, Meme-Otron allows you to "pipe" parts in order to compose more advanced memes. The syntax is as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
[part1] - [part2] - ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Each part can be one of the following:
|
||||||
|
|
||||||
|
* A template: as described in [Simple use](#simple-use)
|
||||||
|
* Texts: ```text "text 1" "text 2" ...```
|
||||||
|
* Black Arial texts on white background
|
||||||
|
* Each text is it's own paragraph
|
||||||
|
* Images: ```image <URL>```
|
||||||
|
* Takes an image from input or an URL (optional)
|
||||||
|
* Input depends on the system:
|
||||||
|
* the Discord bot takes the attachment
|
||||||
|
* the CLI takes stdin or `--input` argument.
|
||||||
|
|
||||||
|
> Notes
|
||||||
|
> * Input of `image` is always the same, don't expect multiple instances of `image` to get different results if you don't indicate an URL
|
||||||
|
|
||||||
|
See [Examples](#examples) to get an idea of how to use it.
|
||||||
|
|
||||||
|
### Discord features
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
Tag the bot and use the above syntax to get started. In addition, you can use the following commands:
|
||||||
|
|
||||||
|
* Use `help` to get a simple help message
|
||||||
|
* Use `list` to get a list of all meme ids
|
||||||
|
* Use `delete` to delete the last message sent by the bot (directed to you)
|
||||||
|
|
||||||
|
To get the template info, just send the meme id without texts.
|
||||||
|
|
||||||
|
> Tip : You can use `\\n` in your texts to add a line break
|
||||||
|
|
||||||
|
Enjoy the full experience of this bot by using direct messages to keep your server free of spam.
|
||||||
|
|
||||||
|
### CLI features
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
In this project directory, you can simply call:
|
||||||
|
```
|
||||||
|
python -m meme_otron [meme id] "text1" "text2" ... > output.jpg
|
||||||
|
```
|
||||||
|
Without pipe redirection with `-o [output]`:
|
||||||
|
```
|
||||||
|
python -m meme_otron -o output.png [meme id] "text1" "text2" ...
|
||||||
|
```
|
||||||
|
|
||||||
|
You can even pipe input images like this:
|
||||||
|
```
|
||||||
|
python -m meme_otron [arguments] < input.jpg > output.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
Available arguments:
|
||||||
|
* `--help` / `-h`
|
||||||
|
* Show a simple guide
|
||||||
|
* `--output [file]` / `-o [file]`
|
||||||
|
* Output file, you are free to choose the format
|
||||||
|
* `--input [file]` / `-i [file]`
|
||||||
|
* Input file used for `image`
|
||||||
|
* `-nw` / `--no-watermark`
|
||||||
|
* Removes the watermark
|
||||||
|
* `-d` / `--debug`
|
||||||
|
* Add more info to output like a box show the texts boundaries
|
||||||
|
* `-v` / `--verbose`
|
||||||
|
* Add more logging
|
||||||
|
|
||||||
|
|
||||||
|
## List of templates
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
You can find here the full list of templates.
|
||||||
|
Each one has extra info and an image showing how texts are placed.
|
||||||
|
Click on an image to enlarge it.
|
||||||
|
|
||||||
|
### Standard Templates
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--LIST1-START-->
|
||||||
|
|
||||||
|
<!--LIST1-END-->
|
||||||
|
|
||||||
|
### Reactions (no text)
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--LIST2-START-->
|
||||||
|
|
||||||
|
<!--LIST2-END-->
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Simple template
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE1-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE1-END-->
|
||||||
|
|
||||||
|
### Example 2: Use of empty texts
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE2-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE2-END-->
|
||||||
|
|
||||||
|
### Example 3: Text + template
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE3-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE3-END-->
|
||||||
|
|
||||||
|
|
||||||
|
### Example 4: Complex composition
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE4-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE4-END-->
|
||||||
+105
-12
@@ -1,12 +1,25 @@
|
|||||||
|
# Meme-Otron guide
|
||||||
|
|
||||||
* [Commands](#commands)
|
* [Commands](#commands)
|
||||||
|
* [Simple use](#simple-use)
|
||||||
|
* [Advanced use](#advanced-use)
|
||||||
* [Discord features](#discord-features)
|
* [Discord features](#discord-features)
|
||||||
* [CLI features](#cli-features)
|
* [CLI features](#cli-features)
|
||||||
* [List of templates](#list-of-templates)
|
* [List of templates](#list-of-templates)
|
||||||
* [List of reactions](#list-of-templates)
|
* [Standard Templates](#standard-templates)
|
||||||
|
* [Reactions (no text)](#reactions-no-text)
|
||||||
|
* [Examples](#examples)
|
||||||
|
* [Example 1: Simple template](#example-1-simple-template)
|
||||||
|
* [Example 2: Use of empty texts](#example-2-use-of-empty-texts)
|
||||||
|
* [Example 3: Text + Template](#example-3-text--template)
|
||||||
|
* [Example 4: Complex composition](#example-4-complex-composition)
|
||||||
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
### Simple use
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
You can generate memes by using the following arguments:
|
You can generate memes by using the following arguments:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -22,7 +35,36 @@ Depending of the number of `"text"` arguments, several behavior occurs:
|
|||||||
> * You don't have to use all texts shown on the templates
|
> * You don't have to use all texts shown on the templates
|
||||||
> * You can use an empty text argument ( `""` ) to skip a text and keep it blank
|
> * You can use an empty text argument ( `""` ) to skip a text and keep it blank
|
||||||
|
|
||||||
## Discord features
|
See [Examples](#examples) to get an idea of how to use it.
|
||||||
|
|
||||||
|
### Advanced use
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
Since version 1.3, Meme-Otron allows you to "pipe" parts in order to compose more advanced memes. The syntax is as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
[part1] - [part2] - ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Each part can be one of the following:
|
||||||
|
|
||||||
|
* A template: as described in [Simple use](#simple-use)
|
||||||
|
* Texts: ```text "text 1" "text 2" ...```
|
||||||
|
* Black Arial texts on white background
|
||||||
|
* Each text is it's own paragraph
|
||||||
|
* Images: ```image <URL>```
|
||||||
|
* Takes an image from input or an URL (optional)
|
||||||
|
* Input depends on the system:
|
||||||
|
* the Discord bot takes the attachment
|
||||||
|
* the CLI takes stdin or `--input` argument.
|
||||||
|
|
||||||
|
> Notes
|
||||||
|
> * Input of `image` is always the same, don't expect multiple instances of `image` to get different results if you don't indicate an URL
|
||||||
|
|
||||||
|
See [Examples](#examples) to get an idea of how to use it.
|
||||||
|
|
||||||
|
### Discord features
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
Tag the bot and use the above syntax to get started. In addition, you can use the following commands:
|
Tag the bot and use the above syntax to get started. In addition, you can use the following commands:
|
||||||
|
|
||||||
@@ -36,7 +78,8 @@ To get the template info, just send the meme id without texts.
|
|||||||
|
|
||||||
Enjoy the full experience of this bot by using direct messages to keep your server free of spam.
|
Enjoy the full experience of this bot by using direct messages to keep your server free of spam.
|
||||||
|
|
||||||
## CLI features
|
### CLI features
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
In this project directory, you can simply call:
|
In this project directory, you can simply call:
|
||||||
```
|
```
|
||||||
@@ -47,25 +90,75 @@ Without pipe redirection with `-o [output]`:
|
|||||||
python -m meme_otron -o output.png [meme id] "text1" "text2" ...
|
python -m meme_otron -o output.png [meme id] "text1" "text2" ...
|
||||||
```
|
```
|
||||||
|
|
||||||
> Note: with `-o`, you are free to choose the output format
|
You can even pipe input images like this:
|
||||||
|
```
|
||||||
|
python -m meme_otron [arguments] < input.jpg > output.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
Available arguments:
|
||||||
|
* `--help` / `-h`
|
||||||
|
* Show a simple guide
|
||||||
|
* `--output [file]` / `-o [file]`
|
||||||
|
* Output file, you are free to choose the format
|
||||||
|
* `--input [file]` / `-i [file]`
|
||||||
|
* Input file used for `image`
|
||||||
|
* `-nw` / `--no-watermark`
|
||||||
|
* Removes the watermark
|
||||||
|
* `-d` / `--debug`
|
||||||
|
* Add more info to output like a box show the texts boundaries
|
||||||
|
* `-v` / `--verbose`
|
||||||
|
* Add more logging
|
||||||
|
|
||||||
|
|
||||||
## List of templates
|
## List of templates
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
You can find here the full list of templates.
|
You can find here the full list of templates.
|
||||||
Each one has extra info and an image showing how texts are placed.
|
Each one has extra info and an image showing how texts are placed.
|
||||||
Click on an image to enlarge it.
|
Click on an image to enlarge it.
|
||||||
|
|
||||||
|
### Standard Templates
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
<!--START1-->
|
<!--LIST1-START-->
|
||||||
|
|
||||||
<!--END1-->
|
<!--LIST1-END-->
|
||||||
|
|
||||||
## List of reactions
|
### Reactions (no text)
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
You can find here the full list of reactions (templates without texts).
|
<!--LIST2-START-->
|
||||||
Each one has extra info.
|
|
||||||
Click on an image to enlarge it.
|
|
||||||
|
|
||||||
<!--START2-->
|
<!--LIST2-END-->
|
||||||
|
|
||||||
<!--END2-->
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Example 1: Simple template
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE1-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE1-END-->
|
||||||
|
|
||||||
|
### Example 2: Use of empty texts
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE2-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE2-END-->
|
||||||
|
|
||||||
|
### Example 3: Text + template
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE3-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE3-END-->
|
||||||
|
|
||||||
|
|
||||||
|
### Example 4: Complex composition
|
||||||
|
<sub><sup>[↑ back to top](#meme-otron-guide)</sup></sub>
|
||||||
|
|
||||||
|
<!--EXAMPLE4-START-->
|
||||||
|
|
||||||
|
<!--EXAMPLE4-END-->
|
||||||
+69
-28
@@ -1,10 +1,12 @@
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
from typing import List
|
||||||
import PIL
|
import PIL
|
||||||
from os import path
|
from os import path
|
||||||
from meme_otron import img_factory
|
from meme_otron import img_factory
|
||||||
from meme_otron import meme_db
|
from meme_otron import meme_db
|
||||||
from meme_otron import utils
|
from meme_otron import utils
|
||||||
|
from meme_otron import meme_otron
|
||||||
|
|
||||||
logging.basicConfig(format="[%(asctime)s][%(levelname)s][%(module)s] %(message)s", level=logging.WARNING)
|
logging.basicConfig(format="[%(asctime)s][%(levelname)s][%(module)s] %(message)s", level=logging.WARNING)
|
||||||
|
|
||||||
@@ -13,12 +15,58 @@ meme_db.load_memes()
|
|||||||
|
|
||||||
templates_dir = utils.relative_path(__file__, "templates")
|
templates_dir = utils.relative_path(__file__, "templates")
|
||||||
preview_dir = utils.relative_path(__file__, "preview")
|
preview_dir = utils.relative_path(__file__, "preview")
|
||||||
|
doc_template_file = utils.relative_path(__file__, "README-template.md")
|
||||||
doc_file = utils.relative_path(__file__, "README.md")
|
doc_file = utils.relative_path(__file__, "README.md")
|
||||||
|
|
||||||
COLUMNS = 3
|
COLUMNS = 3
|
||||||
IMG_HEIGHT = 400
|
IMG_HEIGHT = 400
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
make_empty(templates_dir)
|
||||||
|
make_empty(preview_dir)
|
||||||
|
|
||||||
|
with open(doc_template_file, mode='r') as f:
|
||||||
|
content = "".join(f.readlines())
|
||||||
|
|
||||||
|
full_list = sorted(meme_db.LIST)
|
||||||
|
template_list = [meme_id for meme_id in full_list if len(meme_db.get_meme(meme_id).texts) > 0]
|
||||||
|
reaction_list = [meme_id for meme_id in full_list if meme_id not in template_list]
|
||||||
|
|
||||||
|
content = produce_template_list(content, "LIST1", template_list)
|
||||||
|
content = produce_template_list(content, "LIST2", reaction_list)
|
||||||
|
|
||||||
|
content = produce_example(content, "EXAMPLE1", "example1.jpg", "",
|
||||||
|
"brain3",
|
||||||
|
"Making memes using an image editor",
|
||||||
|
"Making memes using a Python script",
|
||||||
|
"Making memes using a Discord bot")
|
||||||
|
|
||||||
|
content = produce_example(content, "EXAMPLE2", "example2.jpg",
|
||||||
|
"The 5th text is not set and the 3rd is explicitly set to empty",
|
||||||
|
"see_that_guy",
|
||||||
|
"See that guy over there?",
|
||||||
|
"He uses an image editor to make memes",
|
||||||
|
"",
|
||||||
|
"meme-otron dev")
|
||||||
|
|
||||||
|
content = produce_example(content, "EXAMPLE3", "example3.jpg",
|
||||||
|
"Note how texts make paragraphs",
|
||||||
|
"text",
|
||||||
|
"*Meme has a 'made with meme-otron' watermark*",
|
||||||
|
"reddit: ...",
|
||||||
|
"9gag: ...",
|
||||||
|
"meme-otron dev:",
|
||||||
|
"-",
|
||||||
|
"culture",
|
||||||
|
"meme otron")
|
||||||
|
|
||||||
|
# TODO example 4 : complex composition
|
||||||
|
|
||||||
|
with open(doc_file, mode='w') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
|
||||||
def make_empty(target_dir: str):
|
def make_empty(target_dir: str):
|
||||||
if path.exists(target_dir):
|
if path.exists(target_dir):
|
||||||
for file in os.listdir(target_dir):
|
for file in os.listdir(target_dir):
|
||||||
@@ -28,13 +76,9 @@ def make_empty(target_dir: str):
|
|||||||
os.mkdir(target_dir)
|
os.mkdir(target_dir)
|
||||||
|
|
||||||
|
|
||||||
make_empty(templates_dir)
|
def produce_template_list(content: str, tag: str, id_list: List[str]):
|
||||||
make_empty(preview_dir)
|
|
||||||
|
|
||||||
|
|
||||||
def produce_doc(id_list):
|
|
||||||
if len(id_list) == 0:
|
if len(id_list) == 0:
|
||||||
return ""
|
return content
|
||||||
doc_content = "|" * (COLUMNS + 1) \
|
doc_content = "|" * (COLUMNS + 1) \
|
||||||
+ "\n|" + ":---:|" * COLUMNS
|
+ "\n|" + ":---:|" * COLUMNS
|
||||||
info_line = None
|
info_line = None
|
||||||
@@ -65,31 +109,28 @@ def produce_doc(id_list):
|
|||||||
f"</a>|"
|
f"</a>|"
|
||||||
print(i, meme_id)
|
print(i, meme_id)
|
||||||
doc_content += "|" * (COLUMNS - (i % COLUMNS))
|
doc_content += "|" * (COLUMNS - (i % COLUMNS))
|
||||||
return doc_content
|
return inject_content(doc_content, content, tag)
|
||||||
|
|
||||||
|
|
||||||
full_list = sorted(meme_db.LIST)
|
def produce_example(content: str, tag: str, file_name: str, note: str, *args: str):
|
||||||
template_list = [meme_id for meme_id in full_list if len(meme_db.get_meme(meme_id).texts) > 0]
|
doc_content = f"> {note}\n\n" \
|
||||||
reaction_list = [meme_id for meme_id in full_list if meme_id not in template_list]
|
"```\n" + \
|
||||||
|
" \n".join(['"' + a + '"' if ' ' in a or len(a) == 0 else a for a in args]) + \
|
||||||
|
"\n```\n\n" \
|
||||||
|
f""
|
||||||
|
img, err = meme_otron.compute(*args)
|
||||||
|
if img is not None:
|
||||||
|
img.save(utils.relative_path(__file__, file_name))
|
||||||
|
return inject_content(doc_content, content, tag)
|
||||||
|
|
||||||
doc_content1 = produce_doc(template_list)
|
|
||||||
doc_content2 = produce_doc(reaction_list)
|
|
||||||
|
|
||||||
with open(doc_file, mode='r') as f:
|
def inject_content(new_content, content, tag):
|
||||||
content = "".join(f.readlines())
|
start_str = f"<!--{tag}-START-->"
|
||||||
|
end_str = f"<!--{tag}-END-->"
|
||||||
|
i0 = content.index(start_str)
|
||||||
|
i1 = content.index(end_str) + len(end_str)
|
||||||
|
return content[:i0] + start_str + "\n" + new_content + "\n" + end_str + content[i1:]
|
||||||
|
|
||||||
i0 = content.index("<!--START1-->")
|
|
||||||
i1 = content.index("<!--END1-->") + len("<!--END1-->")
|
|
||||||
i2 = content.index("<!--START2-->")
|
|
||||||
i3 = content.index("<!--END2-->") + len("<!--END2-->")
|
|
||||||
|
|
||||||
with open(doc_file, mode='w') as f:
|
if __name__ == '__main__':
|
||||||
f.write(content[:i0])
|
main()
|
||||||
f.write("<!--START1-->\n")
|
|
||||||
f.write(doc_content1)
|
|
||||||
f.write("\n<!--END1-->")
|
|
||||||
f.write(content[i1:i2])
|
|
||||||
f.write("<!--START2-->\n")
|
|
||||||
f.write(doc_content2)
|
|
||||||
f.write("\n<!--END2-->")
|
|
||||||
f.write(content[i3:])
|
|
||||||
|
|||||||
Reference in New Issue
Block a user