diff --git a/.github/workflows/dev-deploy.yaml b/.github/workflows/dev-deploy.yaml new file mode 100644 index 0000000..dce3e2e --- /dev/null +++ b/.github/workflows/dev-deploy.yaml @@ -0,0 +1,27 @@ +# .github/workflows/dev-deploy.yaml +name: Dev Polybot Service Deployment + +on: + push: + branches: + - dev + +env: + EC2_PUBLIC_IP: 3.235.247.204 + SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + +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: | + echo "$SSH_PRIVATE_KEY" > mykey.pem + chmod 400 mykey.pem + ssh -o StrictHostKeyChecking=accept-new -i mykey.pem ubuntu@$EC2_PUBLIC_IP "cd PolybotServicePythonFursa && bash deploy.sh" + + + diff --git a/.github/workflows/prod-deploy.yaml b/.github/workflows/prod-deploy.yaml new file mode 100644 index 0000000..34fde94 --- /dev/null +++ b/.github/workflows/prod-deploy.yaml @@ -0,0 +1,26 @@ +# .github/workflows/prod-deploy.yaml +name: Prod Polybot Service Deployment + +on: + push: + branches: + - main + +env: + EC2_PUBLIC_IP: 3.232.132.216 + SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} + +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: | + echo "$SSH_PRIVATE_KEY" > mykey.pem + chmod 400 mykey.pem + ssh -o StrictHostKeyChecking=accept-new -i mykey.pem ubuntu@$EC2_PUBLIC_IP "cd PolybotServicePythonFursa && bash deploy.sh" + + diff --git a/README.md b/README.md index fa90cfd..e8ceda5 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Let's get started... Reference: https://ai.stanford.edu/~syyeung/cvweb/tutorial1.html ### What is a digital image? +##sadsa If we take a closer look on a digital image, we will notice it comprised of individual pixels, diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..7a35e40 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +git checkout dev +git pull dev +sudo systemctl daemon-reload +sudo systemctl restart tel.service diff --git a/polybot/app.py b/polybot/app.py index 469190e..be1d8ba 100644 --- a/polybot/app.py +++ b/polybot/app.py @@ -14,6 +14,8 @@ def index(): return 'Ok' + + @app.route(f'/{TELEGRAM_TOKEN}/', methods=['POST']) def webhook(): req = request.get_json() @@ -22,6 +24,6 @@ def webhook(): if __name__ == "__main__": - bot = Bot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) + bot = ImageProcessingBot(TELEGRAM_TOKEN, TELEGRAM_APP_URL) - 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 7fea847..b0d7090 100644 --- a/polybot/bot.py +++ b/polybot/bot.py @@ -3,7 +3,10 @@ import os import time from telebot.types import InputFile -from polybot.img_proc import Img +from img_proc import Img + + + class Bot: @@ -18,7 +21,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}/',certificate=open('YOURPUBLIC.pem', 'r'), timeout=60) logger.info(f'Telegram Bot information\n\n{self.telegram_bot_client.get_me()}') @@ -75,4 +78,75 @@ def handle_message(self, msg): class ImageProcessingBot(Bot): - pass + def handle_message(self, msg): + logger.info(f'Incoming message: {msg}') + name = msg['chat']['first_name'] + options = ("Please send a photo, with a caption of the filter you want to apply on it.\n" + "- Salt and pepper: Adds random noise the image.\n" + "- Blur: Applies a blurring effect to the image.\n" + "- Contour: Detects edges of objects in the image.\n" + "- Rotate: Rotates the image in clockwise.\n" + "- Segment: Divides the image into regions based on similarities.\n" + "- Concat: Combines two images either horizontally or vertically.\n" + "- Rotate num: Rotates the image in clockwise num times. \n" + " - Done: to quit" + ) + try: + + chat_id = msg['chat']['id'] + if "text" in msg and msg["text"].lower() == '/start': + self.send_text(chat_id, f"Hello {name}, Welcome to Ameer images bot.\n") + self.send_text(chat_id, options) + elif 'text' in msg and msg['text'].lower() == 'done': + self.send_text(chat_id, "Good bye, we well be happy to see you again") + else: + is_image = self.is_current_msg_photo(msg) + if is_image: + img = Img(self.download_user_photo(msg)) + filter_option = msg['caption'].strip().split(' ') + if len(filter_option) == 1: + self.send_text(chat_id, f'{filter_option[0]}...') + if filter_option[0].lower() == "blur": + img.blur() + elif filter_option[0].lower() == "rotate": + img.rotate() + elif filter_option[0].lower() == "contour": + img.contour() + elif filter_option[0].lower() == 'segment': + img.segment() + elif filter_option[0].lower() == 'concat': + img2_path = self.download_user_photo(msg) + img2 = Img(img2_path) + img.concat(img2) + else: + self.send_text(chat_id, "Invalid filter") + return + + elif len(filter_option) > 1: + if filter_option[0].lower() == "salt": + self.send_text(chat_id, f'{filter_option[0]} {filter_option[1]} ...') + img.salt_n_pepper() + elif filter_option[0].lower() == "rotate": + self.send_text(chat_id, f'{filter_option[0]} image {filter_option[1]} times..') + try: + num = int(filter_option[1].strip()) + for i in range(num): + img.rotate() + except: + self.send_text(chat_id, "Invalid filter") + return + else: + self.send_text(chat_id, "Invalid filter") + return + + else: + self.send_text(chat_id, "invalid filter") + return + new_path = img.save_img() + self.send_photo(chat_id, new_path) + else: + self.send_text(chat_id, options) + + except Exception as e: + logger.error(f'Error: {e}') + self.send_text(msg['chat']['id'], 'Something went Wrong, Try Again...\n') diff --git a/polybot/img_proc.py b/polybot/img_proc.py index 137ca70..9815c00 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,42 @@ def contour(self): self.data[i] = res def rotate(self): - # TODO remove the `raise` below, and write your implementation - raise NotImplementedError() + if len(self.data) == len(self.data[0]): + for i in range(len(self.data)): + for j in range(i): + tmp = self.data[i][j] + self.data[i][j] = self.data[j][i] + self.data[j][i] = tmp + else: + self.data = [list(row) for row in zip(*self.data[::-1])] 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[i])): + rnd = random.random() + if rnd < 0.2: + self.data[i][j] = 255 + elif rnd > 0.8: + self.data[i][j] = 0 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) or len(self.data[0]) != len(other_img.data[0]): + raise RuntimeError("ERROR: images dimensions are not compatible") + if direction == 'horizontal': + for i in range(len(other_img.data)): + self.data[i] += other_img.data[i] + elif direction == 'vertical': + for i in range(len(other_img.data)): + self.data.append(other_img.data[i]) + else: + raise RuntimeError("ERROR: invalid direction") + 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[i])): + if self.data[i][j] > 100: + self.data[i][j] = 255 + else: + self.data[i][j] = 0 +