Skip to content

Commit

Permalink
refactor: Major refactor for v2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tjtanjin committed Jan 31, 2024
1 parent 699a963 commit fdf3ae6
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 51 deletions.
2 changes: 2 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BOT_TOKEN=YOUR_BOT_TOKEN_HERE
HEALTHCHECKS_ENDPOINT=YOUR_HEALTHCHECKS_ENDPOINT
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
max-line-length = 100
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# These are supported funding model platforms

github: [tjtanjin]
21 changes: 21 additions & 0 deletions .github/workflows/deployment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Deployment
run-name: Deployment

on:
workflow_run:
workflows: ["Docker Hub"]
types:
- completed

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
steps:
- name: executing deployment script
uses: appleboy/[email protected]
with:
host: ${{ secrets.DEPLOYMENT_HOST }}
username: ${{ secrets.DEPLOYMENT_USERNAME }}
password: ${{ secrets.DEPLOYMENT_PASSWORD }}
script: cd tele-qr/ && ./scripts/deploy.sh tele-qr
39 changes: 39 additions & 0 deletions .github/workflows/docker-hub.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Docker Hub
run-name: Docker Hub

on:
push:
branches: [ "master" ]

env:
REGISTRY: docker.io
IMAGE_NAME: ${{ github.repository }}

jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3

- name: Log in to Docker Hub
uses: docker/login-action@40891eba8c2bcd1309b07ba8b11232f313e86779
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@c4ee3adeed93b1fa6a762f209fb01608c1a22f1e
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push Docker image
uses: docker/build-push-action@91df6b874e498451163feb47610c87c4a218c1ee
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
24 changes: 22 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
.DS_Store
/config
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# temp files
/images

# build files
/dist

# test logs
/tests/*.log

# editors
.idea/
.vscode/

# env vars
.env

# misc
.DS_Store
16 changes: 16 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM python:3.10.12

MAINTAINER Tan Jin (tjtanjin)

# set a directory for the app
WORKDIR /usr/src/app

# copy all the files to the container
COPY . .

# install app-specific dependencies
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install python-telegram-bot[job-queue]

# app command
CMD ["python", "-u", "./main.py"]
41 changes: 27 additions & 14 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from submodules import user_input as ui
import json
import os

from dotenv import load_dotenv
from health_ping import HealthPing
from telegram.ext import Application, CommandHandler, MessageHandler, filters

from submodules.user_input import show_help, get_input

dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
load_dotenv(dotenv_path)

HealthPing(url="https://hc-ping.com/613b74f2-e71b-49de-95e5-f8b617d23525",
schedule="1 * * * *",
retries=[60, 300, 720]).start()


def main():
print("Running...")
with open("./config/token.json", "r") as file:
token = json.load(file)["token"]
updater = Updater(token, use_context=True, workers=4)
dp = updater.dispatcher
dp.add_handler(CommandHandler('start', ui.show_help))
dp.add_handler(CommandHandler('help', ui.show_help))
dp.add_handler(MessageHandler(Filters.text, ui.get_input))
updater.start_polling()
updater.idle()
"""
Handles the initial launch of the program (entry point).
"""
token = os.getenv("BOT_TOKEN")
application = Application.builder().token(token).concurrent_updates(True).read_timeout(30).write_timeout(30).build() # noqa
application.add_handler(CommandHandler('start', show_help))
application.add_handler(CommandHandler('help', show_help))
application.add_handler(MessageHandler(filters.TEXT, get_input))
print("TeleQR instance started!")
application.run_polling()


if __name__ == '__main__':
main()
main()
5 changes: 5 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
python-telegram-bot==20.7
python-dotenv==1.0.1
qrcode==7.4.2
Requests==2.31.0
schedule==1.2.1
33 changes: 33 additions & 0 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

# checks if container name is supplied
if [ "$#" -eq 0 ]
then
echo "Please specify a container name!"
exit 1
fi

# checks if container exist
if [ "$(docker ps -a -q -f name=$1)" ]
then
echo "An existing container with the name $1 was found!"

# checks if container is running and stop it if it is
if [ "$(docker ps -aq -f status=running -f name=$1)" ]
then
echo "Stopping container..."
docker stop $1
echo "Container stopped."
fi

# removes stopped container
echo "Removing stopped container..."
docker rm $1
echo "Container removed."
fi

# pull the latest image
docker pull tjtanjin/tele-qr:master

# run new docker container
docker run -d --restart always --name $1 --env-file ./.env tjtanjin/tele-qr:master
3 changes: 2 additions & 1 deletion submodules/qr_handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import qrcode


def generate_qr(chat_id, user_input):
"""
The function generates a QR code image and saves it to be returned to the user.
Expand All @@ -9,4 +10,4 @@ def generate_qr(chat_id, user_input):
"""
img = qrcode.make(user_input)
img.save('./images/{}.png'.format(chat_id))
return None
return None
60 changes: 26 additions & 34 deletions submodules/user_input.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,45 @@
from telegram import ParseMode
from telegram.ext.dispatcher import run_async
import os
import threading

from telegram.constants import ParseMode
from submodules import qr_handler as qh
import os, threading
from ui.builder import show_animated_loader


#------------------- User input functions -------------------#
@run_async
def show_help(update, context):
# ------------------- User input functions ------------------- #
async def show_help(update, context):
"""
Function to list help commands.
Args:
update: default telegram arg
context: default telegram arg
"""
update.message.reply_text("""Simply send a text to generate a QR for it!\n
Have ideas and suggestions for this mini project? Head over to the <a href="https://github.com/tjtanjin/tele-qr">Project Repository</a>!""", parse_mode=ParseMode.HTML, disable_web_page_preview=True)
await update.message.reply_text("""Simply send a text to generate a QR for it!\n
Have ideas and suggestions for this mini project? Head over to the <a href="https://github.com/tjtanjin/tele-qr">Project Repository</a>!""", parse_mode=ParseMode.HTML, disable_web_page_preview=True) # noqa
return None

@run_async
def get_input(update, context):

async def get_input(update, context):
"""
Function to get input string from user.
Args:
update: default telegram arg
context: default telegram arg
"""
chat_id = update.message.chat.id
generating_qr = False
def load_animation(update, message):
"""
Function that provides loading animation during qr code generation.
Args:
update: default telegram arg
message: message showing progress to user
"""
while generating_qr:
message.edit_text(text="<b>Generating QR Code /</b>", parse_mode=ParseMode.HTML)
message.edit_text(text="<b>Generating QR Code -</b>", parse_mode=ParseMode.HTML)
message.edit_text(text="<b>Generating QR Code \\</b>", parse_mode=ParseMode.HTML)
message.edit_text(text="<b>Generating QR Code |</b>", parse_mode=ParseMode.HTML)
message.edit_text(text="<b>QR Code Generated:</b>", parse_mode=ParseMode.HTML)
return None
try:
generating_qr = True
generating = update.message.reply_text("<b>Generating QR Code |</b>", parse_mode=ParseMode.HTML)
threading.Thread(target=load_animation, args=(update, generating)).start()
qh.generate_qr(chat_id, update.message.text)
generating_qr = False
context.bot.send_document(chat_id=chat_id, document=open('./images/{}.png'.format(chat_id), 'rb'), caption="Here is your QR Code!")
processing_msg = await update.message.reply_text("<b>Generating QR Code |</b>",
parse_mode=ParseMode.HTML)
conversion_process = threading.Thread(target=qh.generate_qr,
args=(chat_id, update.message.text))
conversion_process.start()
while conversion_process.is_alive():
await show_animated_loader(processing_msg)

await context.bot.send_document(chat_id=chat_id,
document=open('./images/{}.png'.format(chat_id), 'rb'),
caption="Here is your QR Code!")
os.remove("./images/{}.png".format(chat_id))
except:
context.bot.send_message(chat_id=chat_id, text='An error has occurred. Please open an issue at our <a href="https://github.com/tjtanjin/tele-qr">Project Repository</a>!', parse_mode=ParseMode.HTML, disable_web_page_preview=True)
return None
except (Exception,):
await context.bot.send_message(chat_id=chat_id, text='An error has occurred. Please open an issue at our <a href="https://github.com/tjtanjin/tele-qr">Project Repository</a>!', parse_mode=ParseMode.HTML, disable_web_page_preview=True) # noqa
return None
14 changes: 14 additions & 0 deletions ui/builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from telegram.constants import ParseMode


async def show_animated_loader(message):
"""
Provides loading animation during media conversions.
Args:
message: message to edit to show loader
"""
await message.edit_text(text="<b>Generating QR Code /</b>", parse_mode=ParseMode.HTML)
await message.edit_text(text="<b>Generating QR Code -</b>", parse_mode=ParseMode.HTML)
await message.edit_text(text="<b>Generating QR Code \\</b>", parse_mode=ParseMode.HTML)
await message.edit_text(text="<b>Generating QR Code |</b>", parse_mode=ParseMode.HTML)
return None

0 comments on commit fdf3ae6

Please sign in to comment.