Skip to content

Commit

Permalink
🔧 refactor(cli): remove download-dir option and update logic for stic…
Browse files Browse the repository at this point in the history
…ker downloads

📚 docs(README): update usage instructions and command descriptions
  • Loading branch information
sudoskys committed Oct 18, 2024
1 parent 2e61873 commit 08c6282
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 93 deletions.
135 changes: 62 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,56 @@

## 📘 Overview

`tsticker` is a command-line interface (CLI) tool designed to streamline the creation and management of Telegram
stickers. It automatically adjusts image sizes and suggests appropriate emojis based on image names. The tool supports
both static and animated stickers (in webm format).
`tsticker` is a telegram sticker pack management cli.

Just by adding or deleting files, you can easily update the contents of your sticker pack - making it incredibly
user-friendly!
Just put your images in the `<sticker dir>/stickers` directory and run `tsticker push` to override your cloud sticker
with local stickers.

![intro](.github/intro.png)

## ✨ Key Features
Or you can use the `tsticker sync` command to override your local sticker pack with the cloud sticker pack.

- **Emoji Suggestions:** Automatically suggests emojis based on image names, enhancing user experience.
- **Automatic Image Adjustment:** Resizes and adjusts images to meet Telegram's sticker requirements.
- **Support for Multiple Sticker Types:** Manages both static and animated stickers seamlessly.
- **git-like Operations:** Follows a workflow similar to Git with `init`, `sync`, and `push` commands.
- **Support Gif Conversion:** No problem with transparent background GIF conversion.
Simple? Yes, it is!

## 📋 Prerequisites
- Auto select emoji for sticker
- Auto resize image for sticker
- Auto convert (gif,webm,mov ...) to webm for animated sticker

## 📦 Commands

Ensure the following dependencies are installed before using `tsticker`:
| Command | Description |
|---------------------|--------------------------------------------------------------------------------------------------|
| `tsticker init` | Initializes a new sticker pack. |
| `tsticker sync` | **Override**, Syncs the sticker pack from your local directory with changes from the cloud. |
| `tsticker push` | **Override**, Pushes changes from your local directory to the cloud, updating existing stickers. |
| `tsticker login` | Logs in to your Telegram account. |
| `tsticker logout` | Logs out of your Telegram account. |
| `tsticker help` | Displays help information for the CLI. |
| `tsticker download` | Downloads the sticker pack from the cloud to your local directory. |
| `tsticker trace` | Import cloud sticker pack from url. |

| Dependency | Installation Link |
|------------|-----------------------------------------------------|
| **ffmpeg** | [Download ffmpeg](https://ffmpeg.org/download.html) |
| Example | Description |
|------------------------------------------------------------------|------------------------------------------|
| `tsticker init -s regular -n 'sticker_id' -t 'My sticker title'` | Initialize a new sticker |
| `tsticker sync` | Sync sticker pack |
| `tsticker push` | Push sticker pack |
| `tsticker login -t <token> -u <user>` | Log in to Telegram |
| `tsticker logout` | Log out of Telegram |
| `tsticker download -l <sticker link>` | Download sticker pack, cant make changes |
| `tsticker trace -l <sticker link>` | Import sticker pack(can make changes) |

## 🛠️ Installation
**If you encounter any issues, please [create a new Issue](https://github.com/sudoskys/tsticker/issues) on our GitHub
repository.**

### Installing Dependencies
## 📋 Prerequisites

Install necessary dependencies based on your operating system:
Wait! Before installing `tsticker`, ensure that your computer meets the following requirements:

You need install [ImageMagick](https://docs.wand-py.org/en/0.6.12/guide/install.html) before using this CLI.
- [install ffmpeg](https://ffmpeg.org/download.html)

Install Guide: https://docs.wand-py.org/en/0.6.12/guide/install.html
- [install ImageMagick](https://docs.wand-py.org/en/0.6.12/guide/install.html)

### Installing `tsticker`
## Installing `tsticker`

The recommended way to install `tsticker` is through `pipx` for isolated environments:

Expand All @@ -60,86 +74,61 @@ If you want to upgrade `tsticker` to the latest version, use the following comma
pipx upgrade tsticker
```

## 🔑 Bot Token Setup
## 🔑 Login with Telegram

To create and manage stickers with `tsticker`, you need a Telegram Bot Token. Follow these steps:
We need create a bot as a bridge to manage stickers.

Remember the bot can **only** **auto** manage stickers **created by the bot itself**, once you lost your bot, you can
only manage stickers manually.

To create and manage stickers with `tsticker`, you need a **Telegram Bot Token**. Follow these steps:

1. Open Telegram and search for the [BotFather](https://t.me/BotFather) bot.
2. Start a conversation with BotFather and send the command `/newbot`.
3. Follow the instructions to create your bot and acquire the bot token.

The bot token provided by BotFather will be used as your `BotToken`.

We use https://pypi.org/project/keyring/ to manage your tokens, which may require additional steps. If you encounter
problems, refer to: https://github.com/jaraco/keyring

## 🚀 Usage

### Initial Setup
Win + R, type `cmd`, and press Enter to open the command prompt. Run the following command to login

**Log in to your Telegram account:**
Replace `<token>` with your Telegram bot token and `<user>` with your Telegram user ID (you can get your user ID
from [getidsbot](https://t.me/getidsbot) by sending `/my_id`).

```bash
tsticker login -t <token> -u <user>
```

Replace `<token>` with your Telegram bot token and `<user>` with your Telegram user ID (you can get your user ID
from [getidsbot](https://t.me/getidsbot)).

### Main Commands

| Command | Description |
|-----------------|------------------------------------------------------------------------------------|
| `tsticker init` | Initializes a new sticker pack. |
| `tsticker sync` | Syncs the sticker pack from your local directory with changes from the cloud. |
| `tsticker push` | Pushes changes from your local directory to the cloud, updating existing stickers. |

**Example usage:**

```bash
mkdir <folder_name>
cd <folder_name>
tsticker init -n <pack_name> -t <pack_title>
```
We use https://pypi.org/project/keyring/ to manage your tokens, which may require additional steps. If you encounter
problems, refer to: https://github.com/jaraco/keyring

- `<pack_name>`: The desired directory name for your sticker pack.
- `<pack_title>`: The title for your sticker pack.
## Adding or Removing Stickers

### Adding or Removing Stickers
Just put your images in the `<pack>/stickers` directory and run `tsticker push` to override your cloud sticker pack with
the local sticker pack. We support almost all image formats, including `png`, `jpg`, `jpeg`, `gif`, `webm`, and
`mov` and so on.

To manage your stickers, simply add or remove images or animated files (GIFs/WebMs) in `<pack>/stickers` directory. After
making changes, use the following command to synchronize with your Telegram sticker pack:
Please don't operate lots of stickers at once time, if there is any error, it will break your workflow, but you can
use `tsticker sync` to recover.

```bash
tsticker push
```

If you encounter any issues, please [create a new Issue](https://github.com/sudoskys/tsticker/issues) on our GitHub
repository.
even there are auto-resize and auto-convert, there still have some bad input such as too large image, too long video, so
be careful.

## ⚠️ Important Notes
## Limitations of `tsticker`

| Note | Description |
|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **No Support for Tgs Stickers** | `tgs` format is not supported for this cli. |
| **Rate Limiting** | Each request is throttled to 2 seconds to avoid being blocked by Telegram. |
| **Limited Emoji Auto-Selection** | Automatic emoji selection may not work optimally for all languages, primarily supported for English. check `github@telegram_sticker_utils:telegram_sticker_utils/core/rules.json` |
| **Rate Limits** | Avoid excessive uploads in a short period to prevent Telegram from throttling your bot's actions. |
| **Security** | Keep your bot token secure. Stickers can only be managed through your bot or the official @Stickers bot by the sticker pack creator. |
| Note | Description |
|---------------------------------|----------------------------------------------------------------------------------------------------------------------|
| **No Support for Tgs Stickers** | `tgs` format is not supported for this cli. We using mixed `png` and `webm` format for static and animated stickers. |
| **Rate Limiting** | Each request is throttled to 2 seconds to avoid being blocked by Telegram. |
| **Only Bot User** | Stickers can only be managed through your bot or the official @Stickers bot by the sticker pack creator. |

## 📄 License

`tsticker` is released under the MIT License. See [LICENSE](LICENSE) for more information.

## 🤝 Contributing

Contributions are welcome! If you want to contribute, please follow our [Contributing Guide](CONTRIBUTING.md).

## 🙏 Acknowledgments

Special thanks to all contributors who have made `tsticker` better. For issues or feature requests, please use
the [GitHub issue tracker](https://github.com/sudoskys/tsticker/issues).

---

Enhance your Telegram sticker creation process with `tsticker` and become part of our community striving to simplify
Expand Down
48 changes: 28 additions & 20 deletions src/tsticker/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,22 +321,21 @@ async def logout():


@asyncclick.command()
@asyncclick.option('-d', '--download-dir', default='.', help='Directory to download stickers')
@asyncclick.option('-l', '--link', required=True, help='Link for downloading stickers')
async def download(download_dir: str, link: str):
async def download(link: str):
"""Download stickers from Telegram."""
credentials = get_credentials()
if not credentials:
console.print("[bold red]You are not logged in. Please login first.[/]")
console.print("[bold red]You are not logged in. To access telegram api, you need to login first.[/]")
return
pack_name = link.removesuffix("/").split("/")[-1]
download_dir = pathlib.Path(download_dir)
if not download_dir.exists():
console.print(f"[bold red]Download directory does not exist: {download_dir}[/]")
root_download_dir = pathlib.Path(os.getcwd())
if not root_download_dir.exists():
console.print(f"[bold red]Download directory does not exist: {root_download_dir}[/]")
return
console.print(f"[bold blue]Preparing to download pack: {pack_name} to {download_dir.as_posix()}[/]")
console.print(f"[bold blue]Preparing to download pack: {pack_name} to {root_download_dir.as_posix()}[/]")
telegram_bot = AsyncTeleBot(credentials.token)
await download_sticker_set(pack_name, telegram_bot, download_dir)
await download_sticker_set(pack_name, telegram_bot, root_download_dir)
console.print("[bold green]Download completed![/]")


Expand All @@ -351,21 +350,29 @@ async def trace(link: str):
_pack_name = link.removesuffix("/").split("/")[-1]
try:
telegram_bot = AsyncTeleBot(credentials.token)
cloud_sticker_set = await limited_request(
cloud_sticker_set: StickerSet = await limited_request(
AsyncTeleBot(credentials.token).get_sticker_set(_pack_name)
)
except Exception as e:
console.print(f"[bold red]Failed to get sticker set for {_pack_name}: {e}[/]")
console.print(
f"[bold red]Cant fetch stickers named {_pack_name}: {e}, you cant import a non-exist pack.[/]"
)
return
console.print(
f"[bold blue]Cloud sticker with pack name:[/] {cloud_sticker_set.pack_name}\n"
f"[bold blue]Pack Title:[/] {cloud_sticker_set.pack_title} \n"
f"[bold blue]Cloud sticker with pack name:[/] {cloud_sticker_set.name}\n"
f"[bold blue]Pack Title:[/] {cloud_sticker_set.title} \n"
f"[bold blue]Sticker Type:[/] {cloud_sticker_set.sticker_type}"
)
if not cloud_sticker_set.name.endswith("_by_" + credentials.bot_user.username):
console.print(
f"[bold red]You can only change sticker-set created by BOT USER now logged: @{credentials.bot_user.username} {credentials.bot_user.full_name}[/]"
)
console.print(f"[bold red]The pack name should end with `_by_{credentials.bot_user.username}` [/]")
return
root_dir = pathlib.Path(os.getcwd())
# 尝试使用 Packname 创建文件夹
try:
sticker_dir = root_dir.joinpath(cloud_sticker_set.pack_name)
sticker_dir = root_dir.joinpath(cloud_sticker_set.name)
if sticker_dir.exists():
console.print(f"[bold red]Pack directory already exists:[/] {sticker_dir}")
return
Expand All @@ -377,10 +384,10 @@ async def trace(link: str):
index_file = sticker_dir.joinpath("index.json")
index_file.write_text(
StickerIndexFile.create(
title=cloud_sticker_set.pack_title,
name=cloud_sticker_set.pack_name,
title=cloud_sticker_set.title,
name=cloud_sticker_set.name,
sticker_type=cloud_sticker_set.sticker_type,
operator_id=str(cloud_sticker_set.bot_user.id)
operator_id=str(credentials.bot_user.id)
).model_dump_json(indent=2)
)
# 创建资源文件夹
Expand Down Expand Up @@ -457,7 +464,8 @@ async def init(
# 创建 App
with console.status("[bold blue]Retrieving sticker...[/]", spinner='dots'):
try:
sticker_set = await limited_request(telegram_bot.get_sticker_set(index_file_model.name))
sticker_set: Optional[StickerSet] = await limited_request(
telegram_bot.get_sticker_set(index_file_model.name))
except Exception as e:
if "STICKERSET_INVALID" in str(e):
sticker_set = None
Expand Down Expand Up @@ -513,7 +521,7 @@ async def sync():
return
with console.status("[bold magenta]Retrieving sticker...[/]", spinner='dots'):
try:
now_sticker_set = await limited_request(
now_sticker_set: Optional[StickerSet] = await limited_request(
telegram_bot.get_sticker_set(local_sticker.name)
)
except Exception as e:
Expand Down Expand Up @@ -753,7 +761,7 @@ async def push():
# 获取云端文件
with console.status("[bold yellow]Retrieving sticker...[/]", spinner='dots'):
try:
sticker_set = await limited_request(telegram_bot.get_sticker_set(local_sticker.name))
sticker_set: Optional[StickerSet] = await limited_request(telegram_bot.get_sticker_set(local_sticker.name))
except Exception as e:
if "STICKERSET_INVALID" in str(e):
sticker_set = None
Expand All @@ -772,7 +780,7 @@ async def push():
# 同步索引文件
with console.status("[bold yellow]Synchronizing index...[/]", spinner='dots'):
try:
sticker_set = await limited_request(telegram_bot.get_sticker_set(local_sticker.name))
sticker_set: Optional[StickerSet] = await limited_request(telegram_bot.get_sticker_set(local_sticker.name))
except Exception as e:
if "STICKERSET_INVALID" in str(e):
sticker_set = None
Expand Down

0 comments on commit 08c6282

Please sign in to comment.