diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4db2d10
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,142 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+.vscode
+# C extensions
+*.so
+
+# config files
+*.json
+.env
+
+# temp dir
+Downloads/
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+__pycache__/
+.env
+venv/
+files/
+*.log
+.venv
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5104229
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 drui9
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..453bd9b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+env := .venv
+deps := requirements.txt
+
+run:
+ @clear;./$(env)/bin/python start.py
+
+build:
+ @./$(env)/bin/pip install build;./$(env)/bin/python -m build
+
+clean:
+ @rm -rf dist build *.egg-info **/__pycache__/
+
+stable: clean build
+ git push;git checkout releases;git merge main;git push;twine upload dist/*;git checkout main;
+
+$(env): $(deps)
+ python -m venv $@
+
+install: $(env)
+ @./$(env)/bin/pip install -r $(deps)
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cd29ff1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+
+
+
+
+## Installation :: Python3
+`pip install autogram`
+
+## `An efficient asyncronous Telegram bot API wrapper!`
+Autogram is a telegram BOT API wrapper with focus on simplicity and performance.
+
+## `Why AutoGram?`
+I need a bot framework that makes it easy to administer control remotely.
+
+## `Project TODOs`
+- Plans to cover the entire telegram API methods.
+
+### `footnotes`
+- `Polling` can be implemented by the user, while feeding data to the bot through `bot.parseUpdate(...)`
+- Don't run multiple bots with the same `TOKEN` as this will cause update problems
+- Sending unescaped special characters when using MarkdownV2 will return HTTP400
+- Have `fun` with whatever you're building `;)`
+
diff --git a/autogram.png b/autogram.png
new file mode 100644
index 0000000..6404525
Binary files /dev/null and b/autogram.png differ
diff --git a/autogram/__init__.py b/autogram/__init__.py
new file mode 100644
index 0000000..146e125
--- /dev/null
+++ b/autogram/__init__.py
@@ -0,0 +1,25 @@
+from collections import namedtuple
+#
+ChatActionTypes = namedtuple(
+ 'ChatActions', [
+ 'typing',
+ 'photo',
+ 'video',
+ 'audio',
+ 'document'
+ ])
+#
+chat_actions = ChatActionTypes(
+ 'typing',
+ 'upload_photo',
+ 'upload_video',
+ 'upload_voice',
+ 'upload_document'
+ )
+#
+from autogram.config import Start # noqa: E402
+from autogram.app import Autogram # noqa: E402
+
+__all__ = [
+ 'Start', 'Autogram', 'chat_actions'
+]
diff --git a/autogram/app.py b/autogram/app.py
new file mode 100644
index 0000000..2235379
--- /dev/null
+++ b/autogram/app.py
@@ -0,0 +1,74 @@
+import os
+import time
+import queue
+from autogram.base import Bot
+from requests.exceptions import ConnectionError
+
+
+class Autogram(Bot):
+ def __init__(self, config) -> None:
+ """Initialize parent object"""
+ self.update_handler = None
+ super().__init__(config)
+ return
+
+ def addHandler(self, function):
+ self.update_handler = function
+ return function
+
+ def prepare(self):
+ """Confirm auth through getMe(), then check update methods"""
+ res = self.getMe()
+ if not res.ok:
+ self.do_err(msg=str(res.json()))
+ self.webhook_addr = self.config.get('AUTOGRAM_ENDPOINT') or os.getenv('AUTOGRAM_ENDPOINT') # noqa: E501
+ if self.webhook_addr:
+ res = self.setWebhook(self.webhook_addr)
+ if not res.ok:
+ self.do_err(msg='/setWebhook failed!')
+ else:
+ res = self.deleteWebhook()
+ if not res.ok:
+ self.do_err('/deleteWebhook failed!')
+ else:
+ self.short_poll()
+ return
+
+ def start(self):
+ """Launch the bot"""
+ try:
+ self.prepare()
+ while not self.terminate.is_set():
+ try:
+ if not self.update_handler:
+ time.sleep(5)
+ continue
+ self.update_handler(self.updates.get())
+ except queue.Empty:
+ continue
+ except ConnectionError:
+ self.terminate.set()
+ self.logger.critical('Connection Error!')
+ finally:
+ self.shutdown()
+
+ def shutdown(self):
+ """Gracefully terminate the bot"""
+ if self.terminate.is_set():
+ try:
+ res = self.getWebhookInfo()
+ if not res.ok:
+ return
+ if not res.json()['result']['url']:
+ return
+ except Exception:
+ return
+ # delete webhook and exit
+ try:
+ res = self.deleteWebhook()
+ if not res.ok:
+ raise RuntimeError()
+ except Exception:
+ self.logger.critical('/deleteWebhook failed!')
+ finally:
+ self.terminate.set()
diff --git a/autogram/base.py b/autogram/base.py
new file mode 100644
index 0000000..146bc0d
--- /dev/null
+++ b/autogram/base.py
@@ -0,0 +1,342 @@
+import os
+import re
+import time
+import json
+import loguru
+import threading
+import requests
+from typing import Any
+from queue import Queue
+from requests.models import Response
+from autogram.webserver import WebServer
+from bottle import request, response, post, run, get
+from autogram.config import save_config
+from . import chat_actions
+
+
+class Bot():
+ endpoint = 'https://api.telegram.org/'
+
+ def __init__(self, config :dict) -> None:
+ """Initialize parent database object"""
+ super().__init__()
+ self.updates = Queue()
+ self.logger = loguru.logger
+ self.terminate = threading.Event()
+ self.requests = requests.session()
+ self.config = config or self.do_err(msg='Please pass a config