From 3732209cb1a612022ba3705e524d44c05aee2466 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 13 May 2024 09:58:49 +0300 Subject: [PATCH 01/42] commit --- polybot/img_proc.py | 49 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/polybot/img_proc.py b/polybot/img_proc.py index 137ca70..d85b2e1 100644 --- a/polybot/img_proc.py +++ b/polybot/img_proc.py @@ -1,3 +1,4 @@ +import random from pathlib import Path from matplotlib.image import imread, imsave @@ -51,17 +52,49 @@ def contour(self): self.data[i] = res def rotate(self): - # TODO remove the `raise` below, and write your implementation - raise NotImplementedError() + height = len(self.data) + width = len(self.data[0]) + + # Calculate center of the image + center_x = width // 2 + center_y = height // 2 + + # Create a new array to hold the rotated image + rotated_data = [[0] * height for _ in range(width)] + + # Iterate over each pixel in the original image + for y in range(height): + for x in range(width): + # Calculate new position after rotation + new_x = center_x + (y - center_y) + new_y = center_y - (x - center_x) + + # Assign pixel value from original image to new position in rotated image + rotated_data[new_y][new_x] = self.data[y][x] + + # Update self.data with the rotated image + self.data = rotated_data def salt_n_pepper(self): - # TODO remove the `raise` below, and write your implementation - raise NotImplementedError() + for i in range(len(self.data)): + for j in range(len(self.data[0])): + rand = random.random() + if rand < 0.2: + self.data[i][j] = 255 # Salt + elif rand > 0.8: + self.data[i][j] = 0 # Pepper def concat(self, other_img, direction='horizontal'): - # TODO remove the `raise` below, and write your implementation - raise NotImplementedError() + if len(self.data) != len(other_img.data): + raise RuntimeError("Images have different heights and cannot be concatenated horizontally.") + + self.data = [self_row + other_row for self_row, other_row in zip(self.data, other_img.data)] + def segment(self): - # TODO remove the `raise` below, and write your implementation - raise NotImplementedError() + for i in range(len(self.data)): + for j in range(len(self.data[0])): + if self.data[i][j] > 100: + self.data[i][j] = 255 # White + else: + self.data[i][j] = 0 # Black \ No newline at end of file From c9981dfa5608a8ed04223c5f58277945e22b1aa1 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Fri, 17 May 2024 08:19:08 +0300 Subject: [PATCH 02/42] commit --- README.md | 394 +++++++----------------------- polybot/app.py | 2 +- polybot/bot.py | 63 ++++- polybot/img_proc.py | 39 ++- polybot/test/test_telegram_bot.py | 2 +- 5 files changed, 165 insertions(+), 335 deletions(-) diff --git a/README.md b/README.md index fa90cfd..e326ad7 100644 --- a/README.md +++ b/README.md @@ -1,350 +1,122 @@ +# Image Processing Bot -# The Polybot Service: Python Project [![][autotest_badge]][autotest_workflow] +## Overview -## Background +The Image Processing Bot is a Telegram bot designed to process images based on user-provided captions. Users can send photos with captions such as 'Blur', 'Rotate', 'Concat', etc., and the bot will apply the corresponding filter to the image and send it back. This README provides an overview of the setup, features, and usage instructions for the bot. -In this project, you develop a Python chatbot application which applies filters to images send by users to a Telegram bot. +## Features -Here is a short demonstration: +- **Greet Users**: Responds to messages with 'start', 'hello', or 'hi' with a greeting message. +- **Image Processing**: Supports several image processing functions, including: + - Blur + - Contour + - Rotate + - Segment + - Salt and Pepper + - Concat (concatenates two images) -![app demo](.github/python_project_demo.gif) +## Installation -## Preliminaries +### Prerequisites -1. Fork this repo by clicking **Fork** in the top-right corner of the page. -2. Clone your forked repository by: - ```bash - git clone https://github.com// - ``` - Change `` and `` according to your GitHub username and the name you gave to your fork. E.g. `git clone https://github.com/johndoe/PolybotServicePython`. -3. Open the repo as a code project in your favorite IDE (Pycharm, VSCode, etc..). - It is also a good practice to create an isolated Python virtual environment specifically for your project ([see here how to do it in PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html)). +- Python 3.6+ +- Telegram Bot Token (You can get this by talking to [BotFather](https://core.telegram.org/bots#botfather) on Telegram) +- Flask +- Loguru +- Matplotlib -Later on, you are required to change the `README.md` file content to provide relevant information about your service project, e.g. how to launch the app, main features, etc. +### Steps -Let's get started... +1. **Clone the repository:** -## Intro to image processing + ```bash + git clone https://github.com/your-repo/image-processing-bot.git + cd polybot + ``` -Reference: https://ai.stanford.edu/~syyeung/cvweb/tutorial1.html +2. **Install dependencies:** -### What is a digital image? + ```bash + pip install -r requirements.txt + ``` +3. **Set environment variables:** -If we take a closer look on a digital image, we will notice it comprised of individual pixels, -each pixel has its own value. For a grayscale image, each pixel would have an **intensity** value between 0 and 255, with 0 being black and 255 being white. + Set the following environment variables with your Telegram bot token and webhook URL. -![][python_project_pixel] + ```bash + export TELEGRAM_TOKEN='your-telegram-bot-token' + export TELEGRAM_APP_URL='your-app-url' + ``` -A grayscale image, then, can be represented as a matrix of pixel values: +4. **Run the bot:** -![][python_project_imagematrix] + ```bash + python app.py + ``` -A color image is just a simple extension of this. The colors are constructed from a combination of Red, Green, and Blue (RGB). Instead of one matrix of pixel values, we use 3 different matrix, one for the Red (R) values, one for Green (G), and one Blue (B) values. +## Usage - +### Starting the Bot -As can be seen, each pixel of the image has three channels, represent the red, green, blue values. +Send a message with 'start', 'hello', or 'hi' to the bot to receive a greeting message. -Python-wise, a digital grayscale image is essentially a matrix (list of lists): +### Sending a Photo -![][python_project_pythonimage] +Send a photo with one of the following captions to apply the corresponding filter: -Each element in the `image` list is a list represented a **row** of pixels. +- 'Blur' +- 'Contour' +- 'Rotate' +- 'Segment' +- 'Salt and Pepper' +- 'Concat' (requires a second photo, specified in the message) -### Image filtering +### Example -Filtered images are ubiquitous in our social media feeds, news articles, books—everywhere! -Image filtering is a technique in image processing that involves modifying or enhancing an image by applying a filter to it. -Filters can be used to remove noise, sharpen edges, blur or smooth the image, or highlight specific features or details, among other effects. +1. **Start the bot:** -Python-wise, image filtering is as simple as manipulate the pixel values. + ``` + You: start + Bot: Hi there! I'm your Image Processing Bot. Send me a photo with a caption like 'Blur', 'Rotate', 'Concat', etc., and I'll apply the filter for you! + ``` -## The `Img` class +2. **Send a photo with a caption:** -Under `polybot/img_proc.py`, the `Img` class is designed for image filtering on grayscale images. -Here is a detailed usage instruction for the class: + ``` + You: (Send a photo with the caption 'Blur') + Bot: (Sends back the blurred photo) + ``` -1. Creating an instance of `Img`: +## Code Explanation - Provide the path to the image file as a parameter when creating an instance of the `Img` class, for example: - - ```python - my_img = Img('path/to/image.jpg') - ``` +### `Bot` Class -2. Saving the modified image: - After performing operations on the image, you can save the modified image using the `save_img()` method, for example: - - ```python - my_img.save_img() - ``` - - This will save the modified grayscale image to a new path with an appended `_filtered` suffix, and uses the same file extension. +- **`__init__`**: Initializes the bot, sets up the webhook. +- **`send_text`**: Sends a text message to a chat. +- **`send_text_with_quote`**: Sends a text message with a quoted message. +- **`is_current_msg_photo`**: Checks if the current message contains a photo. +- **`download_user_photo`**: Downloads the photo sent by the user. +- **`send_photo`**: Sends a photo to a chat. +- **`handle_message`**: Handles incoming messages. -### Filters for you to implement +### `QuoteBot` Class -You are instructed to implement at least the following 4 filters: `concat()`, `rotate()`, `salt_n_pepper()`, `segment()`. +Inherits from `Bot`, handles messages by quoting them. -On every error (E.g. image path doesn't exist, input image is not an RGB) you should raise a `RuntimeError` exception. +### `ImageProcessingBot` Class +Inherits from `Bot`, processes images based on captions. -#### Concatenating images +- **`process_image`**: Applies filters to the image based on the caption. -The `concat()` method is meant to concatenate two images together horizontally (side by side). - - -Implementation instruction for horizontal concatenation: -- Check the dimensions of both images to ensure they are compatible for concatenation. If the dimensions are not compatible (e.g., different heights), raise a `RuntimeError` exception with informative message. -- Combine the pixel values of both images to create a new image. For horizontal concatenation, combine each row of the first image with the corresponding row of the second image. -- Store the resulting concatenated image in the `self.data` attribute of the instance. - -```python -my_img = Img('path/to/image.jpg') -another_img = Img('path/to/image2.jpg') -my_img.concat(another_img) -my_img.save_img() # concatenated image was saved in 'path/to/image_filtered.jpg' -``` - -Note: you can optionally use the `direction` argument to implement `vertical` concatenation as well. - -#### Adding "salt and pepper" noise to the image - -The `salt_n_pepper()` noise method applies a type of image distortion that randomly adds isolated pixels with value of either 255 (maximum white intensity) or 0 (minimum black intensity). -The name "salt and pepper" reflects the appearance of these randomly scattered bright and dark pixels, resembling grains of salt and pepper sprinkled on an image. - -Implementation instruction: - 1. Iterate over the pixels of the image by looping through each row and each pixel value. - 2. For each pixel in the image: - - Randomly generate a number between 0 and 1. - - If the random number is less than 0.2, set the pixel value to the maximum intensity (255) to represent salt. - - If the random number is greater than 0.8, set the pixel value to the minimum intensity (0) to represent pepper. - - If neither condition is met (the random number is in between 0.2 to 0.8), keep the original pixel value without any modification. - - -```python -my_img = Img('path/to/image.jpg') -my_img.salt_n_pepper() -my_img.save_img() # noisy image was saved in 'path/to/image_filtered.jpg' -``` - -#### Rotating the image - -The `rotate()` method rotates an image around its center in a clockwise direction. - -Implementation remarks: -The resulting rotated image will have its rows become the columns, and the columns will become the rows. The pixels in the rotated image will be repositioned based on a clockwise rotation around the center of the original image. For example, the first row in the original image will become the last column in the rotated image, the second row will become the second-to-last column, and so on. - -```python -my_img = Img('path/to/image.jpg') -my_img.rotate() -my_img.rotate() # rotate again for a 180 degrees rotation -my_img.save_img() # rotated image was saved in 'path/to/image_filtered.jpg' -``` - -#### Segmenting the image - -The `segment()` method partitions the image into regions where the pixels have similar attributes, so the image is represented in a more simplified manner, and so we can then identify objects and boundaries more easily. - -Implementation instruction: - 1. Iterate over the pixels of the image by looping through each row and each pixel value. - 2. All pixels with an intensity greater than 100 are replaced with a white pixel (intensity 255) and all others are replaced with a black pixel (intensity 0). - -```python -my_img = Img('path/to/image.jpg') -my_img.segment() -my_img.save_img() -``` - -### Filters for inspiration - -The below two filters was already implemented, you can review these functions to get some inspiration of how might a filter implementation look like. - -#### Blurring the image - -The `blur()` method is already implemented. You can control the blurring level `blur_level` argument (default is 16). - It blurs the image by replacing the value of each pixel by the average of the 16 pixels around him (or any other value, controlled by the `blur_level` argument. The bigger the value, the stronger the blurring level). - -```python -my_img = Img('path/to/image.jpg') -my_img.blur() # or my_img.blur(blur_level=32) for stronger blurring effect -my_img.save_img() -``` - -#### Creating a contour of the image - -The `contour()` method is already implemented. It applies a contour effect to the image by calculating the **differences between neighbor pixels** along each row of the image matrix. - -```python -my_img = Img('path/to/image.jpg') -my_img.contour() -my_img.save_img() -``` - -## Test your filters locally - -Under `polybot/test` you'll find unittests for each filter. - -For example, to execute the test suite for the `concat()` filter, run the below command from the root dir of your repo: - -```bash -python -m polybot.test.test_concat -``` - -An alternative way is to run tests from the Pycharm UI. - -## Create a Telegram Bot - -1. Download and install Telegram Desktop (you can use your phone app as well). -2. Once installed, create your own Telegram Bot by following this section to create a bot. Once you have your telegram token you can move to the next step. - -**Never** commit your telegram token in Git repo, even if the repo is private. -For now, we will provide the token as an environment variable to your chat app. -Later on in the course we will learn better approaches to store sensitive data. - -## Running the Telegram bot locally - -The Telegram app is a flask-based service that responsible for providing a chat-based interface for users to interact with your image processing functionality. -It utilizes the Telegram Bot API to receive user images and respond with processed images. - -The code skeleton for the bot app is already given to you under `polybot/app.py`. -In order to run the server, you have to [provide 2 environment variables](https://www.jetbrains.com/help/objc/add-environment-variables-and-program-arguments.html#add-environment-variables): - -1. `TELEGRAM_TOKEN` which is your bot token. -2. `TELEGRAM_APP_URL` which is your app public URL provided by Ngrok (will be discussed soon). - -Implementing bot logic involves running a local Python script that listens for updates from Telegram servers. -When a user sends a message to the bot, Telegram servers forward the message to the Python app using a method called **webhook** (**long-polling** and **websocket** are other possible methods which wouldn't be used in this project). -The Python app processes the message, executes the desired logic, and may send a response back to Telegram servers, which then delivers the response to the user. - -The webhook method consists of simple two steps: - -Setting your chat app URL in Telegram Servers: - -![][python_project_webhook1] - -Once the webhook URL is set, Telegram servers start sending HTTPS POST requests to the specified webhook URL whenever there are updates, such as new messages or events, for the bot. - -![][python_project_webhook2] - - -You've probably noticed that setting `localhost` URL as the webhook for a Telegram bot can be problematic because Telegram servers need to access the webhook URL over the internet to send updates. -As `localhost` is not accessible externally, Telegram servers won't be able to reach the webhook, and the bot won't receive any updates. - -[Ngrok](https://ngrok.com/) can solve this problem by creating a secure tunnel between the local machine (where the bot is running) and a public URL provided by Ngrok. -It exposes the local server to the internet, allowing Telegram servers to reach the webhook URL and send updates to the bot. - -Sign-up for the Ngrok service (or any another tunneling service to your choice), then install the `ngrok` agent as [described here](https://ngrok.com/docs/getting-started/#step-2-install-the-ngrok-agent). - -Authenticate your ngrok agent. You only have to do this once: - -```bash -ngrok config add-authtoken -``` - -Since the telegram bot service will be listening on port `8443`, start ngrok by running the following command: - -```bash -ngrok http 8443 -``` - -Your bot public URL is the URL specified in the `Forwarding` line (e.g. `https://16ae-2a06-c701-4501-3a00-ecce-30e9-3e61-3069.ngrok-free.app`). -Don't forget to set the `TELEGRAM_APP_URL` env var to your URL. - -In the next step you'll finally run your bot app. - -## Running a simple "echo" Bot - the `Bot` class - -Under `polybot/bot.py` you are given a class called `Bot`. This class implements a simple telegram bot, as follows. - -The constructor `__init__` receives the `token` and `telegram_chat_url` arguments. -The constructor creates an instance of the `TeleBot` object, which is a pythonic interface to Telegram API. You can use this instance to conveniently communicate with the Telegram servers. -Later, the constructor sets the webhook URL to be the `telegram_chat_url`. - -The `polybot/app.py` is the main app entrypoint. It's nothing but a simple flask webserver that uses a `Bot` instance to handle incoming messages, caught in the `webhook` endpoint function. - -The default behavior of the `Bot` class is to "echo" the incoming messages. Try it out! - -## Extending the echo bot - the `QuoteBot` class - -In `bot.py` you are given a class called `QuoteBot` which **inherits** from `Bot`. -Upon incoming messages, this bot echoing the message while quoting the original message, unless the user is asking politely not to quote. - -In `app.py`, change the instantiated instance to the `QuoteBot`: - -```diff -- Bot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) -+ QuoteBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) -``` - -Run this bot and check its behavior. - -## Build your image processing bot - the `ImageProcessingBot` class - -In `bot.py` you are given a class called `ImageProcessingBot` which **inherits** from `Bot`, again. -Upon incoming **photo messages**, this bot downloads the photos and processes them according to the **`caption`** field provided with the message. -The bot will then send the processed image to the user. - -A few notes: - -- Inside the `ImageProcessingBot` class, override `handle_message` method and implement the needed functionality. -- Remember that by inheriting the `Bot` class, you can use all of its methods (such as `send_text`, `download_user_photo`, `send_photo`...). -- Possible `caption` values are: `['Blur', 'Contour', 'Rotate', 'Segment', 'Salt and pepper', 'Concat']`. -- Handle potential errors using `try... except... `. Send an appropriate message to the user (E.g. "something went wrong... please try again"). -- Set a timeout when sending a message to Telegram. -- Use `logger` to log important information in your app. -- Your bot should support the `Blur` and `Contour` filters (those filters have already implemented for you). - -Test your bot on real photos and make sure it's functioning properly. - -> [!TIP] -> When working with Telegram's API, you might encounter situations where your code encounters errors while processing incoming messages. In such cases, Telegram's server will automatically retry sending messages that were not responded to with a status code of 200. This retry mechanism is designed to ensure the reliable delivery of messages. -> If you find that your bot is receiving repeated messages due to this retry mechanism, just review your code and identify any errors or issues that might be causing the message processing failures. - -## Test your bot locally - -You can test your bot logic locally by: - -```bash -python -m polybot.test.test_telegram_bot -``` - -Or via the Pycharm UI. - - -## Extend your bot functionality - -Add any functionality you wish to your bot... - -- Greet the user. -- Add some informative message when user sends photos without captions or with invalid caption value. -- Add your own filters. -- Extend the functionality of the filters, e.g. allow users to specify "Rotate 2" to rotate the image twice). - -**Go wild!!!** - - -## Submission - -Time to submit your solution for testing. - -1. Commit and push your changes. -1. In [GitHub Actions][github_actions], watch the automated test execution workflow (enable Actions if needed). - If there are any failures, click on the failed job and **read the test logs carefully**. Fix your solution, commit and push again. - - -## Good Luck - -[DevOpsTheHardWay]: https://github.com/alonitac/DevOpsTheHardWay -[autotest_badge]: ../../actions/workflows/project_auto_testing.yaml/badge.svg?event=push -[autotest_workflow]: ../../actions/workflows/project_auto_testing.yaml/ -[github_actions]: ../../actions - -[python_project_demo]: https://alonitac.github.io/DevOpsTheHardWay/img/python_project_demo.gif -[python_project_pixel]: https://alonitac.github.io/DevOpsTheHardWay/img/python_project_pixel.gif -[python_project_imagematrix]: https://alonitac.github.io/DevOpsTheHardWay/img/python_project_imagematrix.png -[python_project_pythonimage]: https://alonitac.github.io/DevOpsTheHardWay/img/python_project_pythonimage.png -[python_project_webhook1]: https://alonitac.github.io/DevOpsTheHardWay/img/python_project_webhook1.png -[python_project_webhook2]: https://alonitac.github.io/DevOpsTheHardWay/img/python_project_webhook2.png +### `Img` Class +Handles image processing operations. +- **`blur`**: Applies a blur filter. +- **`contour`**: Applies a contour filter. +- **`rotate`**: Rotates the image. +- **`segment`**: Segments the image. +- **`salt_n_pepper`**: Applies a salt and pepper noise filter. +- **`concat`**: Concatenates two images. diff --git a/polybot/app.py b/polybot/app.py index 469190e..afd0d17 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -22,6 +22,6 @@ def webhook(): if __name__ == "__main__": - bot = Bot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) + bot = QuoteBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot app.run(host='0.0.0.0', port=8443) diff --git a/polybot/bot.py b/polybot/bot.py index 7fea847..1087555 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -75,4 +75,65 @@ def handle_message(self, msg): class ImageProcessingBot(Bot): - pass + def handle_message(self, msg): + try: + logger.info(f'Incoming message: {msg}') + + if 'text' in msg: + if msg['text'].lower() in ['start', 'hello', 'hi']: + self.send_text( + msg['chat']['id'], + "Hi there! I'm your Image Processing Bot. Send me a photo with a caption like 'Blur', " + "'Rotate', 'Concat', etc., and I'll apply the filter for you!" + ) + return + + # Check if the received message contains a photo + if self.is_current_msg_photo(msg): + # Download the photo sent by the user + photo_path = self.download_user_photo(msg) + caption = msg.get('caption', '').lower() + + # Process the photo according to the caption + processed_path = self.process_image(photo_path, caption, msg) + # Send the processed image back to the user + self.send_photo(msg['chat']['id'], processed_path) + else: + # Inform user to send a photo. + self.send_text(msg['chat']['id'], "Please send a photo.") + except Exception as e: + logger.error(f"Error: {e}") + self.send_text(msg['chat']['id'], "Error : please try again") + + def process_image(self, photo_path, caption, msg): + """Process the image according to the provided caption.""" + img = Img(photo_path) + + if caption == 'blur': + img.blur() + elif caption == 'contour': + img.contour() + elif caption == 'rotate': + img.rotate() + elif caption == 'segment': + img.segment() + elif caption == 'salt and pepper': + img.salt_n_pepper() + elif caption == 'concat': + # Check if the message contains information about the second image + second_photo_path = msg.get('second_photo_path') + if second_photo_path: + second_img = Img(second_photo_path) + img.concat(second_img) + else: + raise ValueError("For 'Concat' caption, information about the second image is required.") + else: + raise ValueError( + f"Invalid caption: {caption}. Supported captions are: ['blur', 'contour', 'rotate', 'segment', " + f"'salt and pepper', 'concat']" + ) + + # Save the processed image + processed_path = img.save_img() + return processed_path + diff --git a/polybot/img_proc.py b/polybot/img_proc.py index d85b2e1..01185f3 100644 --- a/polybot/img_proc.py +++ b/polybot/img_proc.py @@ -55,25 +55,16 @@ def rotate(self): height = len(self.data) width = len(self.data[0]) - # Calculate center of the image - center_x = width // 2 - center_y = height // 2 + # Transpose the image (swap rows with columns) + transposed_data = [[self.data[j][i] for j in range(height)] for i in range(width)] - # Create a new array to hold the rotated image - rotated_data = [[0] * height for _ in range(width)] + # Reverse the rows to complete the rotation + for i in range(width): + transposed_data[i] = transposed_data[i][::-1] - # Iterate over each pixel in the original image - for y in range(height): - for x in range(width): - # Calculate new position after rotation - new_x = center_x + (y - center_y) - new_y = center_y - (x - center_x) + # Update the image data with the rotated data + self.data = transposed_data - # Assign pixel value from original image to new position in rotated image - rotated_data[new_y][new_x] = self.data[y][x] - - # Update self.data with the rotated image - self.data = rotated_data def salt_n_pepper(self): for i in range(len(self.data)): @@ -85,12 +76,18 @@ def salt_n_pepper(self): self.data[i][j] = 0 # Pepper def concat(self, other_img, direction='horizontal'): - if len(self.data) != len(other_img.data): - raise RuntimeError("Images have different heights and cannot be concatenated horizontally.") - - self.data = [self_row + other_row for self_row, other_row in zip(self.data, other_img.data)] + if len(self.data[0]) != len(other_img.data[0]): + raise RuntimeError("Images have different widths and cannot be concatenated vertically.") + + if direction == 'horizontal': + if len(self.data) != len(other_img.data): + raise RuntimeError("Images have different heights and cannot be concatenated horizontally.") + self.data = [self_row + other_row for self_row, other_row in zip(self.data, other_img.data)] + elif direction == 'vertical': + self.data += other_img.data + else: + raise ValueError("Invalid direction. Direction must be 'horizontal' or 'vertical'.") - def segment(self): for i in range(len(self.data)): for j in range(len(self.data[0])): diff --git a/polybot/test/test_telegram_bot.py b/polybot/test/test_telegram_bot.py index 8ce7005..426d9b4 100644 --- a/polybot/test/test_telegram_bot.py +++ b/polybot/test/test_telegram_bot.py @@ -101,4 +101,4 @@ def test_contour_with_exception(self, mock_open): if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file From 9f0a651e89a425346b3fcc97b0501f30d0d7c09c Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Fri, 17 May 2024 08:20:55 +0300 Subject: [PATCH 03/42] commit --- polybot/bot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/polybot/bot.py b/polybot/bot.py index 1087555..995251f 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -76,6 +76,7 @@ def handle_message(self, msg): class ImageProcessingBot(Bot): def handle_message(self, msg): + try: logger.info(f'Incoming message: {msg}') From aee0a9700157621d6c608916cea012533cbdd2bc Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Fri, 17 May 2024 08:44:01 +0300 Subject: [PATCH 04/42] commit --- polybot/bot.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/polybot/bot.py b/polybot/bot.py index 995251f..307438b 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -76,21 +76,31 @@ def handle_message(self, msg): class ImageProcessingBot(Bot): def handle_message(self, msg): - try: logger.info(f'Incoming message: {msg}') - if 'text' in msg: - if msg['text'].lower() in ['start', 'hello', 'hi']: - self.send_text( - msg['chat']['id'], - "Hi there! I'm your Image Processing Bot. Send me a photo with a caption like 'Blur', " - "'Rotate', 'Concat', etc., and I'll apply the filter for you!" - ) + choices_msg = ('- Blur\n' + '- Contour\n' + '- Rotate [number of rotations]\n' + '- Salt and pepper\n' + '- Segment\n' + '- Concat') + usage_msg = ('Welcome to the Image Processing Bot!\n' + 'Please send a photo along with a caption specifying the filter you want to apply.\n' + 'Supported filters:\n' + f'{choices_msg}') + + # Check if the message is the /start command + if "text" in msg and msg["text"].strip().lower() == '/start': + self.send_text(msg['chat']['id'], + 'Hello! I am your Image Processing Bot. How can I assist you today?') + self.send_text(msg['chat']['id'], usage_msg) return - # Check if the received message contains a photo - if self.is_current_msg_photo(msg): + is_photo = self.is_current_msg_photo(msg) + + if is_photo: + self.send_text(msg['chat']['id'], 'processing the image...') # Download the photo sent by the user photo_path = self.download_user_photo(msg) caption = msg.get('caption', '').lower() @@ -104,7 +114,9 @@ def handle_message(self, msg): self.send_text(msg['chat']['id'], "Please send a photo.") except Exception as e: logger.error(f"Error: {e}") - self.send_text(msg['chat']['id'], "Error : please try again") + self.send_text(msg['chat']['id'], "Error: Please try again later.") + + def process_image(self, photo_path, caption, msg): """Process the image according to the provided caption.""" From 772334ffe852906990dbc7ccc92810076aa2e7a4 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Fri, 17 May 2024 18:13:44 +0300 Subject: [PATCH 05/42] commit --- polybot/app.py | 5 +-- polybot/bot.py | 92 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 63 insertions(+), 34 deletions(-) diff --git a/polybot/app.py b/polybot/app.py index afd0d17..06422a7 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -17,11 +17,12 @@ def index(): @app.route(f'/{TELEGRAM_TOKEN}/', methods=['POST']) def webhook(): req = request.get_json() - bot.handle_message(req['message']) + if 'message' in req: + bot.handle_message(req['message']) return 'Ok' if __name__ == "__main__": - bot = QuoteBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot + bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot app.run(host='0.0.0.0', port=8443) diff --git a/polybot/bot.py b/polybot/bot.py index 307438b..e00270b 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -116,37 +116,65 @@ def handle_message(self, msg): logger.error(f"Error: {e}") self.send_text(msg['chat']['id'], "Error: Please try again later.") - - - def process_image(self, photo_path, caption, msg): - """Process the image according to the provided caption.""" - img = Img(photo_path) - - if caption == 'blur': - img.blur() - elif caption == 'contour': - img.contour() - elif caption == 'rotate': - img.rotate() - elif caption == 'segment': - img.segment() - elif caption == 'salt and pepper': - img.salt_n_pepper() - elif caption == 'concat': - # Check if the message contains information about the second image - second_photo_path = msg.get('second_photo_path') - if second_photo_path: - second_img = Img(second_photo_path) - img.concat(second_img) + class ImageProcessingBot(Bot): + def handle_message(self, msg): + try: + logger.info(f'Incoming message: {msg}') + options_msg = ('- Blur\n' + '- Contour\n' + '- Rotate [number of rotations]\n' + '- Salt and pepper\n' + '- Segment\n' + '- Concat') + usage_msg = ('Welcome to the Image Processing Bot!\n' + 'Please send a photo along with a caption specifying the filter you want to apply.\n' + 'Supported filters:\n' + f'{options_msg}') + + if "text" in msg and msg["text"].strip().lower() == '/start': + self.send_text(msg['chat']['id'], + 'Hello! I am your Image Processing Bot. How can I assist you today?') + self.send_text(msg['chat']['id'], usage_msg) + return + + is_photo = self.is_current_msg_photo(msg) + if is_photo: + self.send_text(msg['chat']['id'], 'Processing the image...') + photo_path = self.download_user_photo(msg) + caption = msg.get('caption', '').lower() + processed_path = self.process_image(photo_path, caption, msg) + self.send_photo(msg['chat']['id'], processed_path) + else: + self.send_text(msg['chat']['id'], "Please send a photo.") + except Exception as e: + logger.error(f"Error: {e}") + self.send_text(msg['chat']['id'], "Error: Please try again later.") + + def process_image(self, photo_path, caption, msg): + img = Img(photo_path) + if caption == 'blur': + img.blur() + elif caption == 'contour': + img.contour() + elif caption == 'rotate': + img.rotate() + elif caption == 'segment': + img.segment() + elif caption == 'salt and pepper': + img.salt_n_pepper() + elif caption == 'concat': + second_photo_path = msg.get('second_photo_path') + if second_photo_path: + second_img = Img(second_photo_path) + img.concat(second_img) + else: + raise ValueError("For 'Concat' caption, information about the second image is required.") else: - raise ValueError("For 'Concat' caption, information about the second image is required.") - else: - raise ValueError( - f"Invalid caption: {caption}. Supported captions are: ['blur', 'contour', 'rotate', 'segment', " - f"'salt and pepper', 'concat']" - ) - - # Save the processed image - processed_path = img.save_img() - return processed_path + raise ValueError( + f"Invalid caption: {caption}. Supported captions are: ['blur', 'contour', 'rotate', 'segment', " + f"'salt and pepper', 'concat']" + ) + processed_path = img.save_img() + return processed_path + From 8b2ceb8442c7e7e2cb6ff42744b14c5d674565bf Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Fri, 17 May 2024 18:15:46 +0300 Subject: [PATCH 06/42] commit --- polybot/bot.py | 92 ++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 60 deletions(-) diff --git a/polybot/bot.py b/polybot/bot.py index e00270b..307438b 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -116,65 +116,37 @@ def handle_message(self, msg): logger.error(f"Error: {e}") self.send_text(msg['chat']['id'], "Error: Please try again later.") - class ImageProcessingBot(Bot): - def handle_message(self, msg): - try: - logger.info(f'Incoming message: {msg}') - options_msg = ('- Blur\n' - '- Contour\n' - '- Rotate [number of rotations]\n' - '- Salt and pepper\n' - '- Segment\n' - '- Concat') - usage_msg = ('Welcome to the Image Processing Bot!\n' - 'Please send a photo along with a caption specifying the filter you want to apply.\n' - 'Supported filters:\n' - f'{options_msg}') - - if "text" in msg and msg["text"].strip().lower() == '/start': - self.send_text(msg['chat']['id'], - 'Hello! I am your Image Processing Bot. How can I assist you today?') - self.send_text(msg['chat']['id'], usage_msg) - return - - is_photo = self.is_current_msg_photo(msg) - if is_photo: - self.send_text(msg['chat']['id'], 'Processing the image...') - photo_path = self.download_user_photo(msg) - caption = msg.get('caption', '').lower() - processed_path = self.process_image(photo_path, caption, msg) - self.send_photo(msg['chat']['id'], processed_path) - else: - self.send_text(msg['chat']['id'], "Please send a photo.") - except Exception as e: - logger.error(f"Error: {e}") - self.send_text(msg['chat']['id'], "Error: Please try again later.") - - def process_image(self, photo_path, caption, msg): - img = Img(photo_path) - if caption == 'blur': - img.blur() - elif caption == 'contour': - img.contour() - elif caption == 'rotate': - img.rotate() - elif caption == 'segment': - img.segment() - elif caption == 'salt and pepper': - img.salt_n_pepper() - elif caption == 'concat': - second_photo_path = msg.get('second_photo_path') - if second_photo_path: - second_img = Img(second_photo_path) - img.concat(second_img) - else: - raise ValueError("For 'Concat' caption, information about the second image is required.") - else: - raise ValueError( - f"Invalid caption: {caption}. Supported captions are: ['blur', 'contour', 'rotate', 'segment', " - f"'salt and pepper', 'concat']" - ) - processed_path = img.save_img() - return processed_path + def process_image(self, photo_path, caption, msg): + """Process the image according to the provided caption.""" + img = Img(photo_path) + + if caption == 'blur': + img.blur() + elif caption == 'contour': + img.contour() + elif caption == 'rotate': + img.rotate() + elif caption == 'segment': + img.segment() + elif caption == 'salt and pepper': + img.salt_n_pepper() + elif caption == 'concat': + # Check if the message contains information about the second image + second_photo_path = msg.get('second_photo_path') + if second_photo_path: + second_img = Img(second_photo_path) + img.concat(second_img) + else: + raise ValueError("For 'Concat' caption, information about the second image is required.") + else: + raise ValueError( + f"Invalid caption: {caption}. Supported captions are: ['blur', 'contour', 'rotate', 'segment', " + f"'salt and pepper', 'concat']" + ) + + # Save the processed image + processed_path = img.save_img() + return processed_path + From fd18a16c9fbc55e8e3a0843aebef1124afbb216a Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sat, 18 May 2024 10:40:33 +0300 Subject: [PATCH 07/42] commit --- README.md | 139 +++++++++++++++----------------------------- polybot/app.py | 3 +- polybot/bot.py | 51 ++++++++-------- polybot/img_proc.py | 13 +++-- 4 files changed, 86 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index e326ad7..12ff03f 100644 --- a/README.md +++ b/README.md @@ -1,122 +1,79 @@ -# Image Processing Bot +# Image Processing Telegram Bot -## Overview +This Telegram bot allows users to process images with various filters and transformations. -The Image Processing Bot is a Telegram bot designed to process images based on user-provided captions. Users can send photos with captions such as 'Blur', 'Rotate', 'Concat', etc., and the bot will apply the corresponding filter to the image and send it back. This README provides an overview of the setup, features, and usage instructions for the bot. - -## Features - -- **Greet Users**: Responds to messages with 'start', 'hello', or 'hi' with a greeting message. -- **Image Processing**: Supports several image processing functions, including: - - Blur - - Contour - - Rotate - - Segment - - Salt and Pepper - - Concat (concatenates two images) - -## Installation +## Getting Started ### Prerequisites -- Python 3.6+ -- Telegram Bot Token (You can get this by talking to [BotFather](https://core.telegram.org/bots#botfather) on Telegram) -- Flask -- Loguru -- Matplotlib +- Python 3.x +- [Flask](https://pypi.org/project/Flask/) +- [matplotlib](https://pypi.org/project/matplotlib/) +- [python-telegram-bot](https://pypi.org/project/python-telegram-bot/) +- [loguru](https://pypi.org/project/loguru/) -### Steps +### Installation -1. **Clone the repository:** +1. Clone this repository: - ```bash - git clone https://github.com/your-repo/image-processing-bot.git - cd polybot + ```sh + git clone + cd ``` -2. **Install dependencies:** +2. Install the dependencies: - ```bash + ```sh pip install -r requirements.txt ``` -3. **Set environment variables:** +### Usage - Set the following environment variables with your Telegram bot token and webhook URL. - - ```bash - export TELEGRAM_TOKEN='your-telegram-bot-token' - export TELEGRAM_APP_URL='your-app-url' - ``` +1. Set up environment variables: + - `TELEGRAM_TOKEN`: Your Telegram bot token. + - `TELEGRAM_APP_URL`: Your application URL. -4. **Run the bot:** +2. Run the Flask app: - ```bash + ```sh python app.py ``` -## Usage - -### Starting the Bot - -Send a message with 'start', 'hello', or 'hi' to the bot to receive a greeting message. - -### Sending a Photo - -Send a photo with one of the following captions to apply the corresponding filter: - -- 'Blur' -- 'Contour' -- 'Rotate' -- 'Segment' -- 'Salt and Pepper' -- 'Concat' (requires a second photo, specified in the message) - -### Example - -1. **Start the bot:** - - ``` - You: start - Bot: Hi there! I'm your Image Processing Bot. Send me a photo with a caption like 'Blur', 'Rotate', 'Concat', etc., and I'll apply the filter for you! - ``` - -2. **Send a photo with a caption:** - - ``` - You: (Send a photo with the caption 'Blur') - Bot: (Sends back the blurred photo) - ``` + 3. Start chatting with your Telegram bot! Send an image along with a caption specifying the filter or transformation you want to apply. -## Code Explanation + **Examples:** + + - Applying the blur filter: + + ![Blur Example](/path/to/blur_example.png) + + - Applying the contour filter: + + ![Segment Example](/home/abdallah/Pictures/Screenshots/segment.png) -### `Bot` Class + -- **`__init__`**: Initializes the bot, sets up the webhook. -- **`send_text`**: Sends a text message to a chat. -- **`send_text_with_quote`**: Sends a text message with a quoted message. -- **`is_current_msg_photo`**: Checks if the current message contains a photo. -- **`download_user_photo`**: Downloads the photo sent by the user. -- **`send_photo`**: Sends a photo to a chat. -- **`handle_message`**: Handles incoming messages. + -### `QuoteBot` Class +## File Structure -Inherits from `Bot`, handles messages by quoting them. +- `app.py`: Flask application handling Telegram webhook and routing. +- `img_proc.py`: Image processing utilities including filters and transformations. +- `bot.py`: Base class and subclasses for different types of Telegram bots. -### `ImageProcessingBot` Class +## Supported Filters/Transformations -Inherits from `Bot`, processes images based on captions. +- Blur +- Contour +- Rotate +- Salt and Pepper +- Segment +- Concatenation (horizontal/vertical) -- **`process_image`**: Applies filters to the image based on the caption. +## Contributing -### `Img` Class +Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request. -Handles image processing operations. +## License -- **`blur`**: Applies a blur filter. -- **`contour`**: Applies a contour filter. -- **`rotate`**: Rotates the image. -- **`segment`**: Segments the image. -- **`salt_n_pepper`**: Applies a salt and pepper noise filter. -- **`concat`**: Concatenates two images. +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/polybot/app.py b/polybot/app.py index 06422a7..d2f3959 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -17,8 +17,7 @@ def index(): @app.route(f'/{TELEGRAM_TOKEN}/', methods=['POST']) def webhook(): req = request.get_json() - if 'message' in req: - bot.handle_message(req['message']) + bot.handle_message(req['message']) return 'Ok' diff --git a/polybot/bot.py b/polybot/bot.py index 307438b..366dbc2 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -75,22 +75,25 @@ def handle_message(self, msg): class ImageProcessingBot(Bot): + def __init__(self, token, telegram_chat_url): + super().__init__(token, telegram_chat_url) + self.pending_images = {} + def handle_message(self, msg): try: logger.info(f'Incoming message: {msg}') choices_msg = ('- Blur\n' '- Contour\n' - '- Rotate [number of rotations]\n' + '- Rotate\n' '- Salt and pepper\n' '- Segment\n' - '- Concat') + '- Concat [horizontal/vertical]') usage_msg = ('Welcome to the Image Processing Bot!\n' 'Please send a photo along with a caption specifying the filter you want to apply.\n' 'Supported filters:\n' f'{choices_msg}') - # Check if the message is the /start command if "text" in msg and msg["text"].strip().lower() == '/start': self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') @@ -100,26 +103,32 @@ def handle_message(self, msg): is_photo = self.is_current_msg_photo(msg) if is_photo: - self.send_text(msg['chat']['id'], 'processing the image...') - # Download the photo sent by the user + self.send_text(msg['chat']['id'], 'Processing the image...') photo_path = self.download_user_photo(msg) caption = msg.get('caption', '').lower() - # Process the photo according to the caption - processed_path = self.process_image(photo_path, caption, msg) - # Send the processed image back to the user - self.send_photo(msg['chat']['id'], processed_path) + if caption.startswith('concat'): + if msg['chat']['id'] not in self.pending_images: + self.pending_images[msg['chat']['id']] = {'first_image': photo_path} + self.send_text(msg['chat']['id'], 'Please send the second image for concatenation.') + else: + self.pending_images[msg['chat']['id']]['second_image'] = photo_path + concat_direction = 'horizontal' if 'horizontal' in caption else 'vertical' + processed_path = self.process_image(self.pending_images[msg['chat']['id']]['first_image'], + caption, concat_direction, + self.pending_images[msg['chat']['id']]['second_image']) + self.send_photo(msg['chat']['id'], processed_path) + del self.pending_images[msg['chat']['id']] + else: + processed_path = self.process_image(photo_path, caption) + self.send_photo(msg['chat']['id'], processed_path) else: - # Inform user to send a photo. self.send_text(msg['chat']['id'], "Please send a photo.") except Exception as e: logger.error(f"Error: {e}") self.send_text(msg['chat']['id'], "Error: Please try again later.") - - - def process_image(self, photo_path, caption, msg): - """Process the image according to the provided caption.""" + def process_image(self, photo_path, caption, concat_direction=None, second_photo_path=None): img = Img(photo_path) if caption == 'blur': @@ -132,21 +141,17 @@ def process_image(self, photo_path, caption, msg): img.segment() elif caption == 'salt and pepper': img.salt_n_pepper() - elif caption == 'concat': - # Check if the message contains information about the second image - second_photo_path = msg.get('second_photo_path') + elif caption.startswith('concat'): if second_photo_path: second_img = Img(second_photo_path) - img.concat(second_img) + img.concat(second_img, direction=concat_direction) else: - raise ValueError("For 'Concat' caption, information about the second image is required.") + raise ValueError("Second image path is required for concatenation.") else: raise ValueError( f"Invalid caption: {caption}. Supported captions are: ['blur', 'contour', 'rotate', 'segment', " - f"'salt and pepper', 'concat']" + f"'salt and pepper', 'concat horizontal', 'concat vertical']" ) - # Save the processed image processed_path = img.save_img() - return processed_path - + return processed_path \ No newline at end of file diff --git a/polybot/img_proc.py b/polybot/img_proc.py index 01185f3..71c0579 100644 --- a/polybot/img_proc.py +++ b/polybot/img_proc.py @@ -76,14 +76,13 @@ def salt_n_pepper(self): self.data[i][j] = 0 # Pepper def concat(self, other_img, direction='horizontal'): - if len(self.data[0]) != len(other_img.data[0]): - raise RuntimeError("Images have different widths and cannot be concatenated vertically.") - if direction == 'horizontal': if len(self.data) != len(other_img.data): raise RuntimeError("Images have different heights and cannot be concatenated horizontally.") self.data = [self_row + other_row for self_row, other_row in zip(self.data, other_img.data)] elif direction == 'vertical': + if len(self.data[0]) != len(other_img.data[0]): + raise RuntimeError("Images have different widths and cannot be concatenated vertically.") self.data += other_img.data else: raise ValueError("Invalid direction. Direction must be 'horizontal' or 'vertical'.") @@ -94,4 +93,10 @@ def segment(self): if self.data[i][j] > 100: self.data[i][j] = 255 # White else: - self.data[i][j] = 0 # Black \ No newline at end of file + self.data[i][j] = 0 # Black + + +my_img = Img('/home/abdallah/Pictures/Screenshots/img1.png') +another_img = Img('/home/abdallah/Pictures/Screenshots/img2.png') +my_img.concat(another_img , 'horizontal') +my_img.save_img() # concatenated image was saved in 'path/to/image_filtered.jpg' \ No newline at end of file From bc91b6eda93c3dbf76f324188d8f363a800b4eba Mon Sep 17 00:00:00 2001 From: Abdullah Assi <75143506+abd129-0@users.noreply.github.com> Date: Sat, 18 May 2024 10:45:58 +0300 Subject: [PATCH 08/42] commit --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 12ff03f..74751f9 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,21 @@ This Telegram bot allows users to process images with various filters and transf 3. Start chatting with your Telegram bot! Send an image along with a caption specifying the filter or transformation you want to apply. **Examples:** + - Applying /start command: + + ![Screenshot from 2024-05-18 10-42-58](https://github.com/abd129-0/PolybotServicePythonFursa/assets/75143506/f962be9b-a4e0-4bef-9d10-e6b26e21b613) + - Applying the blur filter: - ![Blur Example](/path/to/blur_example.png) + ![Screenshot from 2024-05-18 10-44-55](https://github.com/abd129-0/PolybotServicePythonFursa/assets/75143506/9a371d3b-bda0-4b81-88d0-4b34fd7e1a8c) + - - Applying the contour filter: - - ![Segment Example](/home/abdallah/Pictures/Screenshots/segment.png) + - Applying the segment filter: + + ![segment](https://github.com/abd129-0/PolybotServicePythonFursa/assets/75143506/3d2d5926-fd97-4692-8e3c-1477cde065e7) + + From ec87f369dc3df8f10ef32e6db37e68d84090c8b7 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sat, 18 May 2024 10:48:30 +0300 Subject: [PATCH 09/42] commit --- polybot/bot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/polybot/bot.py b/polybot/bot.py index 366dbc2..f345643 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -148,6 +148,7 @@ def process_image(self, photo_path, caption, concat_direction=None, second_photo else: raise ValueError("Second image path is required for concatenation.") else: + raise ValueError( f"Invalid caption: {caption}. Supported captions are: ['blur', 'contour', 'rotate', 'segment', " f"'salt and pepper', 'concat horizontal', 'concat vertical']" From e41a8ae9a66ab4c62d199e2962c542745391d385 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sat, 18 May 2024 10:50:18 +0300 Subject: [PATCH 10/42] commit --- polybot/img_proc.py | 8 +------- polybot/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/polybot/img_proc.py b/polybot/img_proc.py index 71c0579..281bb41 100644 --- a/polybot/img_proc.py +++ b/polybot/img_proc.py @@ -93,10 +93,4 @@ def segment(self): if self.data[i][j] > 100: self.data[i][j] = 255 # White else: - self.data[i][j] = 0 # Black - - -my_img = Img('/home/abdallah/Pictures/Screenshots/img1.png') -another_img = Img('/home/abdallah/Pictures/Screenshots/img2.png') -my_img.concat(another_img , 'horizontal') -my_img.save_img() # concatenated image was saved in 'path/to/image_filtered.jpg' \ No newline at end of file + self.data[i][j] = 0 # Black \ No newline at end of file diff --git a/polybot/requirements.txt b/polybot/requirements.txt index 9e38157..29b0f99 100644 --- a/polybot/requirements.txt +++ b/polybot/requirements.txt @@ -2,4 +2,4 @@ pyTelegramBotAPI>=4.12.0 loguru>=0.7.0 requests>=2.31.0 flask>=2.3.2 -matplotlib>=3.7.5 \ No newline at end of file +matplotlib>=3.7.5 From 3b34d6efbb79eaae8f861106a12432d69c4d3537 Mon Sep 17 00:00:00 2001 From: Abdullah Assi <75143506+abd129-0@users.noreply.github.com> Date: Sat, 18 May 2024 11:26:48 +0300 Subject: [PATCH 11/42] commit --- README.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 74751f9..81899c6 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,60 @@ This Telegram bot allows users to process images with various filters and transf ```sh pip install -r requirements.txt ``` +### Create a Telegram Bot + +1. Download and install Telegram Desktop (you can use your phone app as well). +2. Once installed, create your own Telegram Bot by following this section to create a bot. Once you have your telegram token you can move to the next step. + +**Never** commit your telegram token in Git repo, even if the repo is private. +For now, we will provide the token as an environment variable to your chat app. +Later on in the course we will learn better approaches to store sensitive data. + +### Running the Telegram bot locally + +The Telegram app is a flask-based service that responsible for providing a chat-based interface for users to interact with your image processing functionality. +It utilizes the Telegram Bot API to receive user images and respond with processed images. + +The code skeleton for the bot app is already given to you under `polybot/app.py`. +In order to run the server, you have to [provide 2 environment variables](https://www.jetbrains.com/help/objc/add-environment-variables-and-program-arguments.html#add-environment-variables): + +1. `TELEGRAM_TOKEN` which is your bot token. +2. `TELEGRAM_APP_URL` which is your app public URL provided by Ngrok (will be discussed soon). + +Implementing bot logic involves running a local Python script that listens for updates from Telegram servers. +When a user sends a message to the bot, Telegram servers forward the message to the Python app using a method called **webhook** (**long-polling** and **websocket** are other possible methods which wouldn't be used in this project). +The Python app processes the message, executes the desired logic, and may send a response back to Telegram servers, which then delivers the response to the user. + +The webhook method consists of simple two steps: + +Setting your chat app URL in Telegram Servers: + +Once the webhook URL is set, Telegram servers start sending HTTPS POST requests to the specified webhook URL whenever there are updates, such as new messages or events, for the bot. + +You've probably noticed that setting `localhost` URL as the webhook for a Telegram bot can be problematic because Telegram servers need to access the webhook URL over the internet to send updates. +As `localhost` is not accessible externally, Telegram servers won't be able to reach the webhook, and the bot won't receive any updates. + +[Ngrok](https://ngrok.com/) can solve this problem by creating a secure tunnel between the local machine (where the bot is running) and a public URL provided by Ngrok. +It exposes the local server to the internet, allowing Telegram servers to reach the webhook URL and send updates to the bot. + +Sign-up for the Ngrok service (or any another tunneling service to your choice), then install the `ngrok` agent as [described here](https://ngrok.com/docs/getting-started/#step-2-install-the-ngrok-agent). + +Authenticate your ngrok agent. You only have to do this once: + +```bash +ngrok config add-authtoken +``` + +Since the telegram bot service will be listening on port `8443`, start ngrok by running the following command: + +```bash +ngrok http 8443 +``` + +Your bot public URL is the URL specified in the `Forwarding` line (e.g. `https://16ae-2a06-c701-4501-3a00-ecce-30e9-3e61-3069.ngrok-free.app`). +Don't forget to set the `TELEGRAM_APP_URL` env var to your URL. + +In the next step you'll finally run your bot app. ### Usage @@ -76,11 +130,3 @@ This Telegram bot allows users to process images with various filters and transf - Salt and Pepper - Segment - Concatenation (horizontal/vertical) - -## Contributing - -Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request. - -## License - -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. From 2a0499f554b4421d97e94423b3f99f42c077810e Mon Sep 17 00:00:00 2001 From: Abdullah Assi <75143506+abd129-0@users.noreply.github.com> Date: Sat, 18 May 2024 19:02:18 +0300 Subject: [PATCH 12/42] commit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81899c6..333c186 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ In the next step you'll finally run your bot app. 2. Run the Flask app: ```sh - python app.py + python polybot/app.py ``` 3. Start chatting with your Telegram bot! Send an image along with a caption specifying the filter or transformation you want to apply. From e971cc374188648870712a3ce9d358bc1478cf81 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Fri, 31 May 2024 22:27:04 +0000 Subject: [PATCH 13/42] some changes --- polybot/app.py | 2 +- polybot/bot.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/polybot/app.py b/polybot/app.py index d2f3959..ca139be 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -24,4 +24,4 @@ def webhook(): if __name__ == "__main__": bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot - app.run(host='0.0.0.0', port=8443) + app.run(host='0.0.0.0', port=8443, ssl_context=('YOURPUBLIC.pem', 'YOURPRIVATE.key')) diff --git a/polybot/bot.py b/polybot/bot.py index f345643..4ddde80 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -3,7 +3,7 @@ import os import time from telebot.types import InputFile -from polybot.img_proc import Img +from img_proc import Img class Bot: @@ -18,7 +18,7 @@ def __init__(self, token, telegram_chat_url): time.sleep(0.5) # set the webhook URL - self.telegram_bot_client.set_webhook(url=f'{telegram_chat_url}/{token}/', timeout=60) + self.telegram_bot_client.set_webhook(url=f'{telegram_chat_url}/{token}/', timeout=60, certificate=open('YOURPUBLIC.pem', 'r')) logger.info(f'Telegram Bot information\n\n{self.telegram_bot_client.get_me()}') @@ -155,4 +155,4 @@ def process_image(self, photo_path, caption, concat_direction=None, second_photo ) processed_path = img.save_img() - return processed_path \ No newline at end of file + return processed_path From b14e2418bdddef5f639d9335af8b4e75982b947a Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Fri, 31 May 2024 23:05:35 +0000 Subject: [PATCH 14/42] added auto deploy --- .github/workflows/dev-deploy.yaml | 30 ++++++++++++++++++++++++++++++ .github/workflows/prod-deploy.yaml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 .github/workflows/dev-deploy.yaml create mode 100644 .github/workflows/prod-deploy.yaml diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml new file mode 100644 index 0000000..2b1b26f --- /dev/null +++ b/.github/workflows/dev-deploy.yaml @@ -0,0 +1,30 @@ +name: dev Polybot Service Deployment + +on: + push: + branches: + - dev + +env: + EC2_PUBLIC_IP: 13.60.97.131 + SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + DOMAIN: dev-bot.abdullahfursa.click:8443 + +jobs: + Deploy: + name: Deploy in EC2 + runs-on: ubuntu-latest + + steps: + - name: Checkout the app code + uses: actions/checkout@v2 + + - name: SSH to EC2 instance + run: | + ssh -o StrictHostKeyChecking=no -i $SSH_PRIVATE_KEY ubuntu@$INSTANCE_IP << 'EOF' + cd /home/ubuntu/PolybotServicePythonFursa/polybot + git pull origin dev + source /home/ubuntu/PolybotServicePythonFursa/polybot/venv/bin/activate + pip install -r requirements.txt + sudo systemctl restart mybot.service + EOF diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml new file mode 100644 index 0000000..2acc884 --- /dev/null +++ b/.github/workflows/prod-deploy.yaml @@ -0,0 +1,30 @@ +name: Prod Polybot Service Deployment + +on: + push: + branches: + - main + +env: + EC2_PUBLIC_IP: 13.60.96.9 + SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + DOMAIN: prod-bot.abdullahfursa.click:8443 + +jobs: + Deploy: + name: Deploy in EC2 + runs-on: ubuntu-latest + + steps: + - name: Checkout the app code + uses: actions/checkout@v2 + + - name: SSH to EC2 instance + run: | + ssh -o StrictHostKeyChecking=no -i $SSH_PRIVATE_KEY ubuntu@$INSTANCE_IP << 'EOF' + cd /home/ubuntu/PolybotServicePythonFursa/polybot + git pull origin main + source /home/ubuntu/PolybotServicePythonFursa/polybot/venv/bin/activate + pip install -r requirements.txt + sudo systemctl restart mybot.service + EOF From 6c750fb8b7d291fbc584aefd0c4fcb1c4c6ce58c Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sat, 1 Jun 2024 07:08:15 +0000 Subject: [PATCH 15/42] yaml files --- .github/workflows/dev-deploy.yaml | 11 ++++++----- .github/workflows/prod-deploy.yaml | 10 +++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 2b1b26f..6f6f936 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -1,4 +1,4 @@ -name: dev Polybot Service Deployment +name: Dev Polybot Service Deployment on: push: @@ -7,6 +7,7 @@ on: env: EC2_PUBLIC_IP: 13.60.97.131 + TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 @@ -21,10 +22,10 @@ jobs: - name: SSH to EC2 instance run: | - ssh -o StrictHostKeyChecking=no -i $SSH_PRIVATE_KEY ubuntu@$INSTANCE_IP << 'EOF' - cd /home/ubuntu/PolybotServicePythonFursa/polybot + echo "$SSH_PRIVATE_KEY" > mykey.pem + chmod 400 mykey.pem + ssh -o StrictHostKeyChecking=no -i mykey.pem ubuntu@$EC2_PUBLIC_IP + cd /home/ubuntu/PolybotServicePythonFursa git pull origin dev - source /home/ubuntu/PolybotServicePythonFursa/polybot/venv/bin/activate - pip install -r requirements.txt sudo systemctl restart mybot.service EOF diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index 2acc884..103dad4 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -7,6 +7,7 @@ on: env: EC2_PUBLIC_IP: 13.60.96.9 + TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 @@ -21,10 +22,9 @@ jobs: - name: SSH to EC2 instance run: | - ssh -o StrictHostKeyChecking=no -i $SSH_PRIVATE_KEY ubuntu@$INSTANCE_IP << 'EOF' - cd /home/ubuntu/PolybotServicePythonFursa/polybot + echo "$SSH_PRIVATE_KEY" > mykey.pem + chmod 400 mykey.pem + ssh -o StrictHostKeyChecking=no -i mykey.pem ubuntu@$EC2_PUBLIC_IP + cd /home/ubuntu/PolybotServicePythonFursa git pull origin main - source /home/ubuntu/PolybotServicePythonFursa/polybot/venv/bin/activate - pip install -r requirements.txt sudo systemctl restart mybot.service - EOF From 7f0b4d08256b1e58d0a4c48378d47a8547b16d81 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sat, 1 Jun 2024 13:06:08 +0300 Subject: [PATCH 16/42] ip added to yaml --- .github/workflows/dev-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 6f6f936..4ba51ba 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 13.60.97.131 + EC2_PUBLIC_IP: 16.171.38.213 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 From 9d34f9494a4e0e2a3e42464c7d4da4f6d5e2fe06 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sat, 1 Jun 2024 13:10:48 +0300 Subject: [PATCH 17/42] ip add to yaml --- .github/workflows/prod-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index 103dad4..3a5d9b7 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -6,7 +6,7 @@ on: - main env: - EC2_PUBLIC_IP: 13.60.96.9 + EC2_PUBLIC_IP: 13.60.105.216 TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 From 82e964301daf6f2d05a8925bf1646f68ac5c3aa7 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sat, 1 Jun 2024 13:23:44 +0300 Subject: [PATCH 18/42] deploy changes --- .github/workflows/dev-deploy.yaml | 7 ++----- .github/workflows/prod-deploy.yaml | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 4ba51ba..6af694c 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -24,8 +24,5 @@ jobs: run: | echo "$SSH_PRIVATE_KEY" > mykey.pem chmod 400 mykey.pem - ssh -o StrictHostKeyChecking=no -i mykey.pem ubuntu@$EC2_PUBLIC_IP - cd /home/ubuntu/PolybotServicePythonFursa - git pull origin dev - sudo systemctl restart mybot.service - EOF + ssh -o StrictHostKeyChecking=no -i mykey.pem ubuntu@$EC2_PUBLIC_IP "bash ~/dev_deploy.sh &" + diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index 3a5d9b7..c650506 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -24,7 +24,5 @@ jobs: run: | echo "$SSH_PRIVATE_KEY" > mykey.pem chmod 400 mykey.pem - ssh -o StrictHostKeyChecking=no -i mykey.pem ubuntu@$EC2_PUBLIC_IP - cd /home/ubuntu/PolybotServicePythonFursa - git pull origin main - sudo systemctl restart mybot.service + ssh -o StrictHostKeyChecking=no -i mykey.pem ubuntu@$EC2_PUBLIC_IP "~/prod_deploy.sh" + From 101e36798155d133af4212826afc685e7d7742d4 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sun, 2 Jun 2024 22:56:03 +0300 Subject: [PATCH 19/42] final --- .github/workflows/dev-deploy.yaml | 2 +- .github/workflows/prod-deploy.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 6af694c..1c361a1 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 16.171.38.213 + EC2_PUBLIC_IP: 51.20.32.7 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index c650506..d0d5fdc 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -6,7 +6,7 @@ on: - main env: - EC2_PUBLIC_IP: 13.60.105.216 + EC2_PUBLIC_IP: 51.20.31.51 TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 From 2b48242a24c9b2cb1c8836b84f84a4e23278a95f Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sun, 2 Jun 2024 23:01:39 +0300 Subject: [PATCH 20/42] final --- .github/workflows/dev-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 6af694c..0c77e69 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 16.171.38.213 + EC2_PUBLIC_IP: 151.20.32.7 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 From b6eff924c6596aacda3706f06f36f89f1bb7e5fc Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sun, 2 Jun 2024 23:03:21 +0300 Subject: [PATCH 21/42] final --- .github/workflows/prod-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index c650506..d0d5fdc 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -6,7 +6,7 @@ on: - main env: - EC2_PUBLIC_IP: 13.60.105.216 + EC2_PUBLIC_IP: 51.20.31.51 TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 From 740f94901aa1cb5c435c3068e10fe744d4948a52 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sun, 2 Jun 2024 23:08:42 +0300 Subject: [PATCH 22/42] final --- polybot/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/polybot/app.py b/polybot/app.py index ca139be..bfb26d0 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -22,6 +22,7 @@ def webhook(): if __name__ == "__main__": + bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot app.run(host='0.0.0.0', port=8443, ssl_context=('YOURPUBLIC.pem', 'YOURPRIVATE.key')) From 4a3562b4dfc6636272bd91c1e75547a69b630e39 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Sun, 2 Jun 2024 23:14:54 +0300 Subject: [PATCH 23/42] final --- .github/workflows/dev-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 0c77e69..1c361a1 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 151.20.32.7 + EC2_PUBLIC_IP: 51.20.32.7 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 From 2e00d95517322855c7a1491981945fe64eb97d20 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 00:08:04 +0300 Subject: [PATCH 24/42] final --- .github/workflows/dev-deploy.yaml | 2 +- .github/workflows/prod-deploy.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 1c361a1..0406186 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 51.20.32.7 + EC2_PUBLIC_IP: 16.171.129.40 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index d0d5fdc..5c8cb8a 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -6,7 +6,7 @@ on: - main env: - EC2_PUBLIC_IP: 51.20.31.51 + EC2_PUBLIC_IP: 16.170.202.142 TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 From 19dd50b09c08e85a6734a2f3e4ce9c63cf31d29e Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 00:29:11 +0300 Subject: [PATCH 25/42] final --- .github/workflows/prod-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index 5c8cb8a..5127d12 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -6,7 +6,7 @@ on: - main env: - EC2_PUBLIC_IP: 16.170.202.142 + EC2_PUBLIC_IP: 16.171.129.40 TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 From 4a6ed80374191260b3c3b8d99d892c4750a8e441 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 00:32:35 +0300 Subject: [PATCH 26/42] final --- .github/workflows/prod-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index 5127d12..5c8cb8a 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -6,7 +6,7 @@ on: - main env: - EC2_PUBLIC_IP: 16.171.129.40 + EC2_PUBLIC_IP: 16.170.202.142 TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 From dd077b0e9dd4a530670305a76c0d4dd6970bc619 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 3 Jun 2024 20:19:57 +0000 Subject: [PATCH 27/42] added files --- .gitignore | 2 ++ polybot/app.py | 2 +- polybot/bot.py | 7 +++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 2dc53ca..aced32c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ eggs/ lib/ lib64/ parts/ +YOURPUBLIC.pem +YOURPRIVATE.key sdist/ var/ wheels/ diff --git a/polybot/app.py b/polybot/app.py index d2f3959..ca139be 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -24,4 +24,4 @@ def webhook(): if __name__ == "__main__": bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot - app.run(host='0.0.0.0', port=8443) + app.run(host='0.0.0.0', port=8443, ssl_context=('YOURPUBLIC.pem', 'YOURPRIVATE.key')) diff --git a/polybot/bot.py b/polybot/bot.py index f345643..b060e63 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -3,7 +3,7 @@ import os import time from telebot.types import InputFile -from polybot.img_proc import Img +from img_proc import Img class Bot: @@ -18,8 +18,7 @@ def __init__(self, token, telegram_chat_url): time.sleep(0.5) # set the webhook URL - self.telegram_bot_client.set_webhook(url=f'{telegram_chat_url}/{token}/', timeout=60) - + self.telegram_bot_client.set_webhook(url=f'{telegram_chat_url}/{token}/', timeout=60, certificate=open('YOURPUBLIC.pem', 'r')) logger.info(f'Telegram Bot information\n\n{self.telegram_bot_client.get_me()}') def send_text(self, chat_id, text): @@ -155,4 +154,4 @@ def process_image(self, photo_path, caption, concat_direction=None, second_photo ) processed_path = img.save_img() - return processed_path \ No newline at end of file + return processed_path From b1507d73aad7146b3b747a58c12d480606b036fb Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 20:37:48 +0000 Subject: [PATCH 28/42] fix --- polybot/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polybot/app.py b/polybot/app.py index bfb26d0..9a0f9a9 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -23,6 +23,6 @@ def webhook(): if __name__ == "__main__": - bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot + bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot1 app.run(host='0.0.0.0', port=8443, ssl_context=('YOURPUBLIC.pem', 'YOURPRIVATE.key')) From dd044c6b3736b3c0787f092bac4fd3cce4ec1a26 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 20:46:48 +0000 Subject: [PATCH 29/42] newfeature --- polybot/bot.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/polybot/bot.py b/polybot/bot.py index 4ddde80..57b36ae 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -97,6 +97,10 @@ def handle_message(self, msg): if "text" in msg and msg["text"].strip().lower() == '/start': self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') + if "text" in msg and msg["text"].strip().lower() == 'start': + self.send_text(msg['chat']['id'], + 'NotValidMSG!!') + self.send_text(msg['chat']['id'], usage_msg) return From 2e87fb09b1cda003b1e50c8108ad6ac1f4bd089b Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 20:53:16 +0000 Subject: [PATCH 30/42] ip added --- .github/workflows/dev-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 0406186..b696034 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 16.171.129.40 + EC2_PUBLIC_IP: 16.171.198.193 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 From 95a5a3aa6060cf07708e0e932e12238ad1c4c7dc Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 21:00:17 +0000 Subject: [PATCH 31/42] A --- polybot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polybot/bot.py b/polybot/bot.py index 57b36ae..f378f7f 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -98,7 +98,7 @@ def handle_message(self, msg): self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') if "text" in msg and msg["text"].strip().lower() == 'start': - self.send_text(msg['chat']['id'], + self.send_text(msg['chat']['id'], 'NotValidMSG!!') self.send_text(msg['chat']['id'], usage_msg) From aac4d06054d939d83ed1e155e55fc5dc8eb136bb Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 21:06:48 +0000 Subject: [PATCH 32/42] ip added --- .github/workflows/dev-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index b696034..32bb0b2 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 16.171.198.193 + EC2_PUBLIC_IP: 51.20.55.12 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 From e8c75b629e8f88c6ad601293daff84580f8b13b6 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 21:10:24 +0000 Subject: [PATCH 33/42] www --- polybot/bot.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/polybot/bot.py b/polybot/bot.py index f378f7f..2f19fe1 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -97,9 +97,6 @@ def handle_message(self, msg): if "text" in msg and msg["text"].strip().lower() == '/start': self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') - if "text" in msg and msg["text"].strip().lower() == 'start': - self.send_text(msg['chat']['id'], - 'NotValidMSG!!') self.send_text(msg['chat']['id'], usage_msg) return From 86add2fa2da0b26c30bf048dac245f70b78138cf Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Mon, 3 Jun 2024 21:44:09 +0000 Subject: [PATCH 34/42] A --- polybot/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polybot/app.py b/polybot/app.py index bfb26d0..9a0f9a9 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -23,6 +23,6 @@ def webhook(): if __name__ == "__main__": - bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot + bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) # Instantiate QuoteBot1 app.run(host='0.0.0.0', port=8443, ssl_context=('YOURPUBLIC.pem', 'YOURPRIVATE.key')) From a8f171e2e2af5c31baec8ed3bbf6cb6ee88067f5 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Tue, 4 Jun 2024 14:39:56 +0000 Subject: [PATCH 35/42] ip changed --- .github/workflows/dev-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 6f6f936..21c6447 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 13.60.97.131 + EC2_PUBLIC_IP: 13.51.158.13 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443 From 7f25b950f6c38b263c7ecaf1c78d46bf835acefd Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 4 Jun 2024 14:44:56 +0000 Subject: [PATCH 36/42] ip added --- .github/workflows/prod-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml index c650506..b0d51c8 100644 --- a/.github/workflows/prod-deploy.yaml +++ b/.github/workflows/prod-deploy.yaml @@ -6,7 +6,7 @@ on: - main env: - EC2_PUBLIC_IP: 13.60.105.216 + EC2_PUBLIC_IP: 16.170.218.102 TOKEN: ${{ secrets.PROD_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: prod-bot.abdullahfursa.click:8443 From 20dea97c2b13c635dac09beac117aba5a7ecd7e6 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Tue, 4 Jun 2024 17:47:04 +0000 Subject: [PATCH 37/42] greeting user --- polybot/bot.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/polybot/bot.py b/polybot/bot.py index 4ddde80..2f0b2cc 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -97,6 +97,9 @@ def handle_message(self, msg): if "text" in msg and msg["text"].strip().lower() == '/start': self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') + if "text" in msg and msg["text"].strip().lower() == 'Hi': + self.send_text(msg['chat']['id'], 'Hello BOTTT!!!') + self.send_text(msg['chat']['id'], usage_msg) return From 6773399ada2bb651b8dcf5a9e40d4b1970078385 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Tue, 4 Jun 2024 19:43:22 +0000 Subject: [PATCH 38/42] fix --- polybot/bot.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/polybot/bot.py b/polybot/bot.py index 931a44c..3090bb8 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -95,10 +95,9 @@ def handle_message(self, msg): f'{choices_msg}') if "text" in msg and msg["text"].strip().lower() == '/start': - self.send_text(msg['chat']['id'], - 'Hello! I am your Image Processing Bot. How can I assist you today?' - if "text" in msg and msg["text"].strip().lower() == 'Hi': - self.send_text(msg['chat']['id'], 'Hello BOTTT!!!') + self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') + if "text" in msg and msg["text"].strip().lower() == 'hi': + self.send_text(msg['chat']['id'], 'Hello BOTTT!!!') self.send_text(msg['chat']['id'], usage_msg) return From 355c5bfe4f0abdac91b7e06be948872b1e022735 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Tue, 4 Jun 2024 19:45:14 +0000 Subject: [PATCH 39/42] fixed --- polybot/bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polybot/bot.py b/polybot/bot.py index 2f0b2cc..087977e 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -97,7 +97,7 @@ def handle_message(self, msg): if "text" in msg and msg["text"].strip().lower() == '/start': self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') - if "text" in msg and msg["text"].strip().lower() == 'Hi': + if "text" in msg and msg["text"].strip().lower() == 'hi': self.send_text(msg['chat']['id'], 'Hello BOTTT!!!') self.send_text(msg['chat']['id'], usage_msg) From fc24d0064ca57370bf0b6716ed93337f52638dc7 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 4 Jun 2024 19:59:58 +0000 Subject: [PATCH 40/42] fixed --- polybot/bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polybot/bot.py b/polybot/bot.py index 54e9d45..3090bb8 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -96,8 +96,8 @@ def handle_message(self, msg): if "text" in msg and msg["text"].strip().lower() == '/start': self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') - if "text" in msg and msg["text"].strip().lower() == 'hi': - self.send_text(msg['chat']['id'], 'Hello BOTTT!!!') + if "text" in msg and msg["text"].strip().lower() == 'hi': + self.send_text(msg['chat']['id'], 'Hello BOTTT!!!') self.send_text(msg['chat']['id'], usage_msg) return From 1f0577f9ce65e5313c90e967bce1cbee661f28d7 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Wed, 5 Jun 2024 13:41:31 +0300 Subject: [PATCH 41/42] feature added --- polybot/bot.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/polybot/bot.py b/polybot/bot.py index 3090bb8..19eed84 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -94,6 +94,8 @@ def handle_message(self, msg): 'Supported filters:\n' f'{choices_msg}') + if "text" in msg and msg["text"].strip().lower() == 'bye': + self.send_text(msg['chat']['id'], 'see you soon') if "text" in msg and msg["text"].strip().lower() == '/start': self.send_text(msg['chat']['id'], 'Hello! I am your Image Processing Bot. How can I assist you today?') if "text" in msg and msg["text"].strip().lower() == 'hi': From db628f2b1a3989d44fcee6744055eaebb918b302 Mon Sep 17 00:00:00 2001 From: abd129-0 Date: Wed, 5 Jun 2024 13:45:32 +0300 Subject: [PATCH 42/42] ip added --- .github/workflows/dev-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml index 710637f..6e5e8c1 100644 --- a/.github/workflows/dev-deploy.yaml +++ b/.github/workflows/dev-deploy.yaml @@ -6,7 +6,7 @@ on: - dev env: - EC2_PUBLIC_IP: 13.51.158.13 + EC2_PUBLIC_IP: 13.60.32.138 TOKEN: ${{ secrets.DEV_TELGRAM_TOKEN}} SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} DOMAIN: dev-bot.abdullahfursa.click:8443