From 871a31f5644cf6ecece5570547ec053c01e66740 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Fri, 28 Mar 2025 20:35:09 +0700 Subject: [PATCH] feat: init --- bulk-telegram-sticker/.env.example | 3 + bulk-telegram-sticker/.gitignore | 3 + bulk-telegram-sticker/README.md | 110 ++++++++++++++++- bulk-telegram-sticker/input/.gitignore | 2 + bulk-telegram-sticker/main.py | 156 ++++++++++++++++++++++++ bulk-telegram-sticker/output/.gitignore | 2 + bulk-telegram-sticker/prepare.py | 97 +++++++++++++++ bulk-telegram-sticker/requirements.txt | 3 + 8 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 bulk-telegram-sticker/.env.example create mode 100644 bulk-telegram-sticker/.gitignore create mode 100644 bulk-telegram-sticker/input/.gitignore create mode 100644 bulk-telegram-sticker/main.py create mode 100644 bulk-telegram-sticker/output/.gitignore create mode 100644 bulk-telegram-sticker/prepare.py create mode 100644 bulk-telegram-sticker/requirements.txt diff --git a/bulk-telegram-sticker/.env.example b/bulk-telegram-sticker/.env.example new file mode 100644 index 0000000..47737c7 --- /dev/null +++ b/bulk-telegram-sticker/.env.example @@ -0,0 +1,3 @@ +PHONE=+1234567890 +API_ID=123456789 +API_HASH=0123456789abcdef0123456789abcdef \ No newline at end of file diff --git a/bulk-telegram-sticker/.gitignore b/bulk-telegram-sticker/.gitignore new file mode 100644 index 0000000..f9736b0 --- /dev/null +++ b/bulk-telegram-sticker/.gitignore @@ -0,0 +1,3 @@ +.idea +.env +*.session \ No newline at end of file diff --git a/bulk-telegram-sticker/README.md b/bulk-telegram-sticker/README.md index 8906df5..170a28a 100644 --- a/bulk-telegram-sticker/README.md +++ b/bulk-telegram-sticker/README.md @@ -1,2 +1,108 @@ -# bulk-telegram-sticker -Create stickers automatically +# Bulk Telegram Sticker Pack Creator + +This tool helps you create and upload sticker packs to Telegram using a two-step process: +1. Prepare and process your images +2. Create and upload the sticker pack + +## Setup + +1. Install the required dependencies: +```bash +pip install -r requirements.txt +``` + +2. Get your Telegram API credentials: + - Go to https://my.telegram.org/auth + - Log in with your phone number + - Go to 'API development tools' + - Create a new application + - Copy the `API_ID` and `API_HASH` + +3. Create a `.env` file in the project root with your credentials: +``` +API_ID=your_api_id +API_HASH=your_api_hash +PHONE=your_phone_number +``` + +## Usage + +### Step 1: Prepare Images + +1. Create an `input` directory in the project root +2. Place your sticker images in the `input` directory (supported formats: PNG, JPG, JPEG) +3. Run the preparation script: +```bash +python prepare.py +``` + +This will: +- Convert all images to WebP format (512x512 pixels) +- Create an `output` directory with the processed images +- Generate a `sticker_config.json` file in the `output` directory + +4. Edit the `output/sticker_config.json` file to: + - Change the sticker pack title and short name + - Modify emojis for each sticker + - Add or remove stickers from the pack + +Example configuration: +```json +{ + "sticker_pack": { + "title": "My Awesome Stickers", + "short_name": "my_awesome_stickers", + "stickers": [ + { + "original": "sticker1.png", + "webp": "sticker1.webp", + "emoji": "😀" + }, + { + "original": "sticker2.png", + "webp": "sticker2.webp", + "emoji": "😎" + } + ] + } +} +``` + +### Step 2: Create Sticker Pack + +1. Run the main script to create and upload the sticker pack: +```bash +python main.py +``` + +2. The first time you run the script, you'll need to authenticate with your phone number +3. The script will create the sticker pack and upload all stickers according to the configuration + +## Important Notes + +- The `short_name` must be unique across all Telegram sticker packs +- Input images will be automatically resized to 512x512 pixels while maintaining aspect ratio +- Images are converted to WebP format with transparency support +- Make sure your input images are clear and of good quality +- The first time you run the script, you'll need to authenticate with your phone number + +## Troubleshooting + +Due to the nature of interacting with Telegram's Sticker bot, some issues may occur: + +1. **Manual Intervention Required**: Sometimes the script may fail to complete the process automatically. In such cases: + - The script will indicate that manual completion is needed + - You can continue the process manually by messaging @Stickers + - Follow the bot's prompts to complete the sticker pack creation + +2. **Common Issues**: + - Bot response delays: The script includes delays between actions, but sometimes the bot may need more time + - Network issues: Ensure you have a stable internet connection + - Rate limiting: If you create multiple packs, Telegram may temporarily limit your actions + +3. **If the Script Fails**: + - Check the error message for specific details + - You can start a new conversation with @Stickers and complete the process manually + - The bot will guide you through the remaining steps + +Remember that while the script automates most of the process, you may need to complete some steps manually if unexpected issues arise. diff --git a/bulk-telegram-sticker/input/.gitignore b/bulk-telegram-sticker/input/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/bulk-telegram-sticker/input/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/bulk-telegram-sticker/main.py b/bulk-telegram-sticker/main.py new file mode 100644 index 0000000..3b98a5d --- /dev/null +++ b/bulk-telegram-sticker/main.py @@ -0,0 +1,156 @@ +import os +import asyncio +import json +from telethon import TelegramClient, events +from telethon.tl.types import InputPeerUser +from telethon.tl.functions.messages import SendMessageRequest +from pathlib import Path +from dotenv import load_dotenv + +# Load environment variables from .env file +load_dotenv() + +# Telegram API credentials +API_ID = os.getenv('API_ID') +API_HASH = os.getenv('API_HASH') +PHONE = os.getenv('PHONE') + +# Sticker bot username +STICKER_BOT_USERNAME = "@Stickers" + +print(f"API_ID: {API_ID}") +print(f"API_HASH: {API_HASH}") +print(f"PHONE: {PHONE}") + +# Initialize the client +client = TelegramClient(PHONE, API_ID, API_HASH) + +def load_config(config_path): + """Load and validate configuration file""" + try: + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + # Validate required fields + if not all(key in config for key in ['title', 'short_name', 'stickers']): + raise ValueError("Missing required fields in configuration") + + return config + except Exception as e: + print(f"Error loading configuration: {str(e)}") + return None + +async def create_sticker_pack(config): + """ + Create a new sticker pack by interacting with the Sticker bot + + Args: + config (dict): Configuration dictionary containing sticker pack details + """ + try: + # Start the client + await client.start(phone=PHONE) + + # Get the sticker bot entity + sticker_bot = await client.get_entity(STICKER_BOT_USERNAME) + + # Start new sticker pack creation + await client(SendMessageRequest( + peer=sticker_bot, + message="/newpack" + )) + + # Wait for bot to ask for pack name + await asyncio.sleep(1) + + # Send pack name + await client(SendMessageRequest( + peer=sticker_bot, + message=config['title'] + )) + + # Wait for bot to ask for short name + await asyncio.sleep(1) + + # Send short name + await client(SendMessageRequest( + peer=sticker_bot, + message=config['short_name'] + )) + + # Wait for bot to ask for username + await asyncio.sleep(1) + + # Send username (using short name) + await client(SendMessageRequest( + peer=sticker_bot, + message=config['short_name'] + )) + + output_dir = "output" + + # Upload stickers one by one + for sticker in config['stickers']: + sticker_path = os.path.join(output_dir, sticker['webp']) + if not os.path.exists(sticker_path): + print(f"Warning: Sticker file not found: {sticker_path}") + continue + + # Send sticker file + await client.send_file( + sticker_bot, + sticker_path, + caption=sticker['emoji'] + ) + + # Wait for bot to process the sticker + await asyncio.sleep(2) + + # Skip any additional prompts + await asyncio.sleep(1) + await client(SendMessageRequest( + peer=sticker_bot, + message="/skip" + )) + await asyncio.sleep(1) + + # Send /publish command to finalize the pack + await client(SendMessageRequest( + peer=sticker_bot, + message="/publish" + )) + + # Wait for bot to ask for confirmation + await asyncio.sleep(1) + + # Confirm publishing + await client(SendMessageRequest( + peer=sticker_bot, + message="Yes" + )) + + print(f"Sticker pack created successfully: {config['short_name']}") + return config['short_name'] + + except Exception as e: + print(f"Error creating sticker pack: {str(e)}") + print("Note: If the script fails, you may need to complete the process manually with the Sticker bot.") + return None + finally: + await client.disconnect() + +async def main(): + # Load configuration + config_path = os.path.join("output", "sticker_config.json") + if not os.path.exists(config_path): + print("Configuration file not found! Please run prepare.py first.") + return + + config = load_config(config_path) + if not config: + return + + await create_sticker_pack(config) + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/bulk-telegram-sticker/output/.gitignore b/bulk-telegram-sticker/output/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/bulk-telegram-sticker/output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/bulk-telegram-sticker/prepare.py b/bulk-telegram-sticker/prepare.py new file mode 100644 index 0000000..12c2b4d --- /dev/null +++ b/bulk-telegram-sticker/prepare.py @@ -0,0 +1,97 @@ +import os +import json +from PIL import Image +import glob +from pathlib import Path + +def convert_to_webp(input_path, output_path, size=(512, 512)): + """Convert image to WebP format with specified size""" + try: + with Image.open(input_path) as img: + # Convert to RGBA if necessary + if img.mode != 'RGBA': + img = img.convert('RGBA') + + # Resize image maintaining aspect ratio + img.thumbnail(size, Image.Resampling.LANCZOS) + + # Create a new image with padding if necessary + new_img = Image.new('RGBA', size, (0, 0, 0, 0)) + offset = ((size[0] - img.size[0]) // 2, (size[1] - img.size[1]) // 2) + new_img.paste(img, offset) + + # Save as WebP + new_img.save(output_path, 'WEBP', quality=90) + return True + except Exception as e: + print(f"Error converting {input_path}: {str(e)}") + return False + +def process_images(input_dir, output_dir): + """Process all images in input directory and convert to WebP""" + # Create output directory if it doesn't exist + Path(output_dir).mkdir(parents=True, exist_ok=True) + + # Supported input formats + input_formats = ['*.png', '*.jpg', '*.jpeg'] + processed_files = [] + + # Process each image + for format in input_formats: + for input_path in glob.glob(os.path.join(input_dir, format)): + filename = os.path.basename(input_path) + name_without_ext = os.path.splitext(filename)[0] + output_path = os.path.join(output_dir, f"{name_without_ext}.webp") + + if convert_to_webp(input_path, output_path): + processed_files.append({ + "original": filename, + "webp": f"{name_without_ext}.webp", + "emoji": "😀" # Default emoji + }) + + return processed_files + +def generate_config(processed_files, output_dir): + """Generate configuration file""" + config = { + "title": "My Awesome Stickers", + "short_name": "my_awesome_stickers", + "stickers": processed_files + } + + # Save config file + config_path = os.path.join(output_dir, "sticker_config.json") + with open(config_path, 'w', encoding='utf-8') as f: + json.dump(config, f, indent=4, ensure_ascii=False) + + return config_path + +def main(): + # Setup directories + input_dir = "input" + output_dir = "output" + + # Create input directory if it doesn't exist + Path(input_dir).mkdir(parents=True, exist_ok=True) + + print("Processing images...") + processed_files = process_images(input_dir, output_dir) + + if not processed_files: + print("No images found in input directory!") + return + + print(f"Processed {len(processed_files)} images") + + # Generate configuration file + config_path = generate_config(processed_files, output_dir) + print(f"\nConfiguration file generated: {config_path}") + print("\nYou can now edit the configuration file to:") + print("1. Change the sticker pack title and short name") + print("2. Modify emojis for each sticker") + print("3. Add or remove stickers from the pack") + print("\nAfter editing, run main.py to create the sticker pack") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/bulk-telegram-sticker/requirements.txt b/bulk-telegram-sticker/requirements.txt new file mode 100644 index 0000000..456d6ff --- /dev/null +++ b/bulk-telegram-sticker/requirements.txt @@ -0,0 +1,3 @@ +telethon>=1.28.5 +python-dotenv>=0.19.0 +Pillow>=10.0.0 \ No newline at end of file