Use file session; Fix HTML to have easier find/replace; Include libs

This commit is contained in:
octospacc 2023-05-10 00:48:56 +02:00
parent b2539699fa
commit ef797f127c
13 changed files with 106 additions and 130 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.session *.session
*.session-journal
.env .env
__pycache__/ __pycache__/
venv/ venv/
@ -10,4 +11,4 @@ app.json
Procfile Procfile
.vscode/ .vscode/
.gitignore .gitignore
pyproject.toml pyproject.toml

View File

@ -15,50 +15,47 @@
- **Clone to local machine.** - **Clone to local machine.**
```bash ```sh
$ git clone https://github.com/odysseusmax/tg-index.git git clone https://github.com/odysseusmax/tg-index.git
cd tg-index
$ cd tg-index
``` ```
- **Create and activate virtual environment.** - **Create and activate virtual environment.**
```bash ```sh
$ python -m venv venv python -m venv venv
source venv/bin/activate
$ source venv/bin/activate
``` ```
- **Install dependencies.** - **Install dependencies.**
```bash ```sh
$ pip3 install -U -r requirements.txt pip3 install -U -r requirements.txt
``` ```
- **Environment Variables.** - **Environment Variables.**
| Variable Name | Value | | Variable Name | Value |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `API_ID` (required) | Telegram api_id obtained from <https://my.telegram.org/apps>. | | `API_ID` (required) | Telegram api_id obtained from <https://my.telegram.org/apps>. |
| `API_HASH` (required) | Telegram api_hash obtained from <https://my.telegram.org/apps>. | | `API_HASH` (required) | Telegram api_hash obtained from <https://my.telegram.org/apps>. |
| `INDEX_SETTINGS` (required) | See the below description. | | `INDEX_SETTINGS` (required) | See the below description. |
| `SESSION_STRING` (required) | String obtained by running `$ python3 app/generate_session_string.py`. (Login with the telegram account which is a participant of the given channel (or chat). | | `PORT` (optional) | Port on which app should listen to, defaults to 8080. |
| `PORT` (optional) | Port on which app should listen to, defaults to 8080. | | `HOST` (optional) | Host name on which app should listen to, defaults to 0.0.0.0. |
| `HOST` (optional) | Host name on which app should listen to, defaults to 0.0.0.0. | | `DEBUG` (optional) | Give `true` to set logging level to debug, info by default. |
| `DEBUG` (optional) | Give `true` to set logging level to debug, info by default. | | `BLOCK_DOWNLOADS` (optional) | Enable downloads or not. If any value is provided, downloads will be disabled. |
| `BLOCK_DOWNLOADS` (optional) | Enable downloads or not. If any value is provided, downloads will be disabled. | | `RESULTS_PER_PAGE` (optional) | Number of results to be returned per page defaults to 20. |
| `RESULTS_PER_PAGE` (optional) | Number of results to be returned per page defaults to 20. | | `TGINDEX_USERNAME` (optional) | Username for authentication, defaults to `''`. |
| `TGINDEX_USERNAME` (optional) | Username for authentication, defaults to `''`. | | `PASSWORD` (optional) | Password for authentication, defaults to `''`. |
| `PASSWORD` (optional) | Password for authentication, defaults to `''`. | | `SHORT_URL_LEN` (optional) | Url length for aliases |
| `SHORT_URL_LEN` (optional) | Url length for aliases | | `SESSION_COOKIE_LIFETIME` (optional) | Number of minutes, for which authenticated session is valid for, after which user has to login again. defaults to 60. |
| `SESSION_COOKIE_LIFETIME` (optional) | Number of minutes, for which authenticated session is valid for, after which user has to login again. defaults to 60. | | `SECRET_KEY` (optional) | 32 characters long string for signing the session cookies, required if authentication is enabled. |
| `SECRET_KEY` (optional) | 32 characters long string for signing the session cookies, required if authentication is enabled. |
- **Setting value for `INDEX_SETTINGS`** - **Setting value for `INDEX_SETTINGS`**
This is the general format, change the values of corresponding fields as your requirements. You can copy paste this as is to index all the channels available in your account. This is the general format, change the values of corresponding fields as your requirements. You can copy paste this as is to index all the channels available in your account.
**Remember to remove spaces.** **Remember to remove newlines.**
```json ```json
{ {
@ -84,18 +81,15 @@ This is the general format, change the values of corresponding fields as your re
python3 -m app python3 -m app
``` ```
Note: you will be asked to **log in** the first time. (Login with the telegram account which is a participant of the chats you want to index).
After that, a `tg-index.session` file will be stored in the current working directory. **Keep it secret and secure**.
## Deploy Guide (Repl.it) ## Deploy Guide (Repl.it)
A detailed and beginner friendly guide on how to deploy this project on a free instance of <https://repl.it> can be found [here](./repl-config/replit-deploy-guide.md). A detailed and beginner friendly guide on how to deploy this project on a free instance of <https://repl.it> can be found [here](./repl-config/replit-deploy-guide.md).
## Contributions ## License, Credits
Contributions are welcome. This program is forked from [odysseusmax/tg-index](https://github.com/odysseusmax/tg-index).
## Contact As per the original, code is released under [The GNU General Public License](LICENSE).
You can contact me [@odysseusmax](https://tx.me/odysseusmax).
## License
Code released under [The GNU General Public License](LICENSE).

View File

@ -34,13 +34,6 @@ except Exception:
print("\n\nPlease set the INDEX_SETTINGS environment variable correctly") print("\n\nPlease set the INDEX_SETTINGS environment variable correctly")
sys.exit(1) sys.exit(1)
try:
session_string = os.environ["SESSION_STRING"]
except (KeyError, ValueError):
traceback.print_exc()
print("\n\nPlease set the SESSION_STRING environment variable correctly")
sys.exit(1)
host = os.environ.get("HOST", "0.0.0.0") host = os.environ.get("HOST", "0.0.0.0")
debug = bool(os.environ.get("DEBUG")) debug = bool(os.environ.get("DEBUG"))
block_downloads = bool(os.environ.get("BLOCK_DOWNLOADS")) block_downloads = bool(os.environ.get("BLOCK_DOWNLOADS"))

View File

@ -1,10 +0,0 @@
import os
from telethon.sync import TelegramClient
from telethon.sessions import StringSession
api_id = int(os.getenv('API_ID') or input("Enter your API_ID: "))
api_hash = os.getenv('API_HASH') or input("Enter your API_HASH: ")
with TelegramClient(StringSession(), api_id, api_hash) as client:
print("\n" + client.session.save())

View File

@ -14,7 +14,6 @@ from .views import Views, middleware_factory
from .config import ( from .config import (
host, host,
port, port,
session_string,
api_id, api_id,
api_hash, api_hash,
authenticated, authenticated,
@ -54,7 +53,7 @@ class Indexer:
self.server.on_startup.append(self.startup) self.server.on_startup.append(self.startup)
self.server.on_cleanup.append(self.cleanup) self.server.on_cleanup.append(self.cleanup)
self.tg_client = Client(session_string, api_id, api_hash) self.tg_client = Client(api_id, api_hash)
self.server["is_authenticated"] = authenticated self.server["is_authenticated"] = authenticated
self.server["username"] = username self.server["username"] = username

View File

@ -3,12 +3,11 @@ import logging
import asyncio import asyncio
from telethon import TelegramClient, utils from telethon import TelegramClient, utils
from telethon.sessions import StringSession
class Client(TelegramClient): class Client(TelegramClient):
def __init__(self, session_string: str, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(StringSession(session_string), *args, **kwargs) super().__init__("tg-index.session", *args, **kwargs)
self.log = logging.getLogger(__name__) self.log = logging.getLogger(__name__)
async def download(self, file, file_size, offset, limit): async def download(self, file, file_size, offset, limit):

View File

@ -1,26 +1,18 @@
</div> </div>
<footer class="w-full my-4 py-4 bg-gray-300 xl:text-xl">
<div class="mx-auto text-center text-black max-w-screen-xl">
<a href="https://github.com/odysseusmax/tg-index" target="_blank"> @odysseusmax </a>
</div>
</footer>
<script> <script>
function toggleTheme() { function toggleTheme() {
element = document.documentElement; var Doc = document.documentElement;
if (element.className == "light") { var Class = Array.from(Doc.classList);
element.className = "dark"; if (Class.includes('light')) {
localStorage.theme = 'dark'; Doc.className = 'dark';
} else { localStorage.theme = 'dark';
element.className = "light"; } else
localStorage.theme = 'light'; if (Class.includes('dark')) {
} Doc.className = 'light';
} localStorage.theme = 'light';
};
function chatImgAlt() { };
document.getElementById('chatimg').src = 'https://s3.imgcdn.dev/nWNtu.jpg'
}
</script> </script>
</body> </body>
</html>
</html>

View File

@ -1,50 +1,52 @@
<!doctype html> <!doctype html>
<html class="light" lang="en"> <html lang="en">
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.1.4/dist/tailwind-dark.min.css" href_="https://cdn.jsdelivr.net/npm/tailwindcss@2.1.4/dist/tailwind.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.1.4/dist/tailwind-dark.min.css" rel="stylesheet"> <script type="text/javascript">
<script src="https://cdn.fluidplayer.com/v3/current/fluidplayer.min.js"> {% include "./js/fluidplayer.min.js" %}
</script> </script>
<script> <script>
(function(){
var Doc = document.documentElement;
Doc.className = 'light';
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.className = 'dark'; Doc.className = 'dark';
} else { } else {
document.documentElement.className = 'light'; Doc.className = 'light';
} };
})();
</script> </script>
<style> <style>
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
* { * {
font-family: 'Roboto', sans-serif; font-family: 'Roboto', 'Liberation Sans', 'Noto Sans', sans-serif;
} }
</style> </style>
<title> <title>
{% if title %} {{title}} {% else %} Telegram Index {% endif %} {% if title %} {{title}} {% else %} Telegram Index {% endif %}
</title> </title>
</head> </head>
<body class="bg-white text-black dark:bg-black dark:text-white"> <body class="bg-white text-black dark:bg-black dark:text-white" style="overflow-x: hidden;">
<header class="bg-blue-300 dark:bg-red-500 text-white mb-2 p-2 w-full shadow"> <header class="bg-blue-300 dark:bg-red-500 text-white mb-2 p-2 w-full shadow">
<div class="flex mx-auto justify-between items-center max-w-screen-xl"> <div class="flex mx-auto justify-between items-center max-w-screen-xl">
<a href="/" id="title-a" class="text-left font-bold text-xl lg:text-2xl xl:text-3xl"> Telegram index </a> <a href="/" id="title-a" class="text-left font-bold text-xl lg:text-2xl xl:text-3xl"> Telegram Index </a>
<div class="space-x-1"> <div class="space-x-1">
<span style="vertical-align: super; white-space: pre;">[<a
href="https://github.com/octospacc/TelegramIndex-Fork" class="font-bold underline"
>Source Code</a>]</span>
<button onclick="toggleTheme()" class="rounded-full bg-white"> <button onclick="toggleTheme()" class="rounded-full bg-white">
<img src="https://s3.imgcdn.dev/nW9YV.png" class="h-8" alt="Theme"> <img src="https://s3.imgcdn.dev/nW9YV.png" class="h-8" alt="Theme"/>
</button> </button>
{% if authenticated %} {% if authenticated %}
<button class="rounded-full bg-white"><a href="/logout"> <button class="rounded-full bg-white"><a href="/logout">
<img src="https://s3.imgcdn.dev/ndsjh.png" class="h-8" alt="Logout"> <img src="https://s3.imgcdn.dev/ndsjh.png" class="h-8" alt="Logout">
</a> </a></button>
</button> {% else %} {% endif %}
{% else %} {% endif %}
</div> </div>
</div> </div>
</header> </header>
<div class="m-auto w-full min-h-screen max-w-screen-xl"> <div class="m-auto w-full max-w-screen-xl">

View File

@ -7,10 +7,10 @@
<div class="mx-auto my-1 p-1 w-full"> <div class="mx-auto my-1 p-1 w-full">
<div class="flex flex-wrap gap-4 justify-center w-full"> <div class="flex flex-wrap gap-4 justify-center w-full">
{% for chat in chats %} {% for chat in chats %}
<a title="{{chat.name}}" href="/{{chat.page_id}}" <a href="/{{chat.page_id}}" title="{{chat.name}}"
class="justify-items-center min-h-full w-5/12 sm:w-1/4 md:w-1/5 lg:w-1/6 rounded p-2 text-center break-words shadow hover:shadow-md hover:bg-blue-100 dark:bg-red-700 dark:hover:bg-red-500"> class="justify-items-center min-h-full w-5/12 sm:w-1/4 md:w-1/5 lg:w-1/6 rounded p-2 text-center break-words shadow hover:shadow-md hover:bg-blue-100 dark:bg-red-700 dark:hover:bg-red-500">
<img src="/{{chat.page_id}}/logo?big=1" class="w-full rounded-full"> <img src="/{{chat.page_id}}/logo?big=1" class="w-full rounded-full"/>
<div class="p-1 mt-2 rounded text-white bg-blue-500 dark:bg-yellow-500">{{chat.name}}</div> <div class="p-1 mt-2 rounded text-white bg-blue-500 dark:bg-yellow-500">{{chat.name}}</div>
</a> </a>
@ -18,4 +18,4 @@
</div> </div>
</div> </div>
{% include 'footer.html' %} {% include 'footer.html' %}

View File

@ -1,14 +1,13 @@
{% include 'header.html' %} {% block javascript %} {% include 'header.html' %} {% block javascript %}
<script type="text/javascript"> <script type="text/javascript">
{% include "./js/filesaver.min.js" %} {% include "./js/filesaver.min.js" %}
{% include "./js/playlist.js" %} {% include "./js/playlist.js" %}
</script> </script>
{% endblock %} {% endblock %}
<div class="block md:flex justify-between items-center px-4 text-center border-b-2"> <div class="block md:flex justify-between items-center px-4 text-center border-b-2">
<div class="m-2 block md:flex items-center justify-center md:justify-start text-2xl md:text-right font-bold text-blue-500"> <div class="m-2 block md:flex items-center justify-center md:justify-start text-2xl md:text-right font-bold text-blue-500">
<img class="mx-auto md:ml-0 md:mr-1 my-4 md:my-2 w-16 h-16 rounded-full bg-black outline-none" src="{{logo}}"> <img src="{{logo}}" class="mx-auto md:ml-0 md:mr-1 my-4 md:my-2 w-16 h-16 rounded-full bg-black outline-none"/>
<a href="javascript:window.location.href=window.location.href"> {{name}} </a> <a href="javascript:window.location.href=window.location.href"> {{name}} </a>
</div> </div>
@ -46,12 +45,11 @@
<!-- Card --> <!-- Card -->
<div title="{% if item.media %} {{item.mime_type}} | {{item.human_size}} {% else %} Text message {% endif %}" <div title="{% if item.media %} {{item.mime_type}} | {{item.human_size}} {% else %} Text message {% endif %}"
href="{{item.url}}"
class="text-sm items-center justify-center w-full min-h-full sm:w-2/5 md:w-1/4 lg:w-1/6 rounded m-2 shadow hover:shadow-lg dark:bg-red-700"> class="text-sm items-center justify-center w-full min-h-full sm:w-2/5 md:w-1/4 lg:w-1/6 rounded m-2 shadow hover:shadow-lg dark:bg-red-700">
{% if item.media %} {% if item.media %}
<a href="{{item.url}}"><img src="{{item.thumbnail}}" class="w-full rounded shadow-inner"></a> <a href="{{item.url}}"><img src="{{item.thumbnail}}" class="w-full rounded shadow-inner"/></a>
<div class="p-2">{{item.insight}}</div> <div class="p-2">{{item.insight}}</div>
<!-- Buttons container --> <!-- Buttons container -->
<span class="inline-flex mb-1 rounded shadow-inner dark:bg-green-500"> <span class="inline-flex mb-1 rounded shadow-inner dark:bg-green-500">
@ -68,7 +66,7 @@
{% if 'video' in item.mime_type %} {% if 'video' in item.mime_type %}
<!-- Kodi/media player supported url ending with v.mp4 --> <!-- Kodi/media player supported url ending with v.mp4 -->
<a title="v.mp4" href="{{item.download}}" <a href="{{item.download}}" title="v.mp4"
class="flex-1 hover:bg-blue-300 text-gray-900 font-semibold py-1 px-2 rounded items-center"> class="flex-1 hover:bg-blue-300 text-gray-900 font-semibold py-1 px-2 rounded items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
stroke="currentColor"> stroke="currentColor">
@ -94,7 +92,7 @@
</span> </span>
{% else %} {% else %}
<a href={{item.url}}> <a href="{{item.url}}">
<div class="p-4 rounded shadow-inner rounded text-dark py-0 px-2">{{item.insight}}</div> <div class="p-4 rounded shadow-inner rounded text-dark py-0 px-2">{{item.insight}}</div>
</a> </a>
{% endif %} {% endif %}
@ -114,17 +112,17 @@
<div class="mx-auto my-2 text-center flex text-white content-center justify-center"> <div class="mx-auto my-2 text-center flex text-white content-center justify-center">
{% if prev_page %} {% if prev_page %}
<a title="Previous page" <a href="{{prev_page.url}}"
class="mx-2 p-2 border rounded bg-green-500 hover:border-green-500 hover:text-green-500 hover:bg-white" class="mx-2 p-2 border rounded bg-green-500 hover:border-green-500 hover:text-green-500 hover:bg-white"
href="{{prev_page.url}}">Page {{prev_page.no}}</a> title="Previous page">Page {{prev_page.no}}</a>
{% endif %} {% endif %}
<p <p
class="mx-2 p-2 border rounded border-green-500 text-green-500 hover:border-green-500 hover:text-green-500 hover:bg-white"> class="mx-2 p-2 border rounded border-green-500 text-green-500 hover:border-green-500 hover:text-green-500 hover:bg-white">
Page {{cur_page}}</p> Page {{cur_page}}</p>
{% if next_page %} {% if next_page %}
<a title="Next page" <a href="{{next_page.url}}"
class="mx-2 p-2 border rounded bg-green-500 hover:border-green-500 hover:text-green-500 hover:bg-white" class="mx-2 p-2 border rounded bg-green-500 hover:border-green-500 hover:text-green-500 hover:bg-white"
href="{{next_page.url}}">Page {{next_page.no}}</a> title="Next page">Page {{next_page.no}}</a>
{% endif %} {% endif %}
</div> </div>
@ -136,4 +134,4 @@
{% endif %} {% endif %}
{% include 'footer.html' %} {% include 'footer.html' %}

View File

@ -9,15 +9,15 @@
<div class="mx-auto w-full p-2 md:w-3/4 lg:w-2/5 p-2"> <div class="mx-auto w-full p-2 md:w-3/4 lg:w-2/5 p-2">
{% if media.image %} {% if media.image %}
<img class="mx-auto rounded" src="{{thumbnail}}" alt="{{name}}"> <img src="{{thumbnail}}" class="mx-auto rounded" alt="{{name}}"/>
{% elif media.video %} {% elif media.video %}
<div id="video-warning" class="mx-auto p-4 bg-gray-600 text-gray-300 rounded border text-center hidden break-words"> <div id="video-warning" class="mx-auto p-4 bg-gray-600 text-gray-300 rounded border text-center hidden break-words">
<p> Video {{name}} could not be played!</p> <p> Video {{name}} could not be played!</p>
</div> </div>
<div id="my-video-wrapper"> <div id="my-video-wrapper">
<video id="my-video-player" class="mx-auto rounded" controls poster="{{thumbnail}}"> <video id="my-video-player" class="mx-auto rounded" controls="controls" poster="{{thumbnail}}">
<source src="{{download_url}}" type="video/mp4" /> <source src="{{download_url}}" type="video/mp4"/>
</video> </video>
</div> </div>
@ -52,9 +52,9 @@
</div> </div>
<div id="my-audio-wrapper"> <div id="my-audio-wrapper">
<img class="mx-auto rounded w-full" src="{{thumbnail}}" alt="{{name}}"> <img src="{{thumbnail}}" class="mx-auto rounded w-full" alt="{{name}}"/>
<audio class="mx-auto" controls muted> <audio class="mx-auto" controls="controls" muted="muted">
<source src="{{download_url}}" type="audio/mpeg" /> <source src="{{download_url}}" type="audio/mpeg"/>
</audio> </audio>
</div> </div>
<script> <script>
@ -80,7 +80,9 @@
{% for row in reply_btns %} {% for row in reply_btns %}
<div class="flex justify-center"> <div class="flex justify-center">
{% for btn in row %} {% for btn in row %}
<a class="p-2 m-1 flex-1 border rounded bg-white border-blue-500 text-center text-blue-500 hover:bg-blue-500 hover:text-white transition ease-in duration-150" href="{{ btn.url }}" target="_blank"> {{btn.text}} </a> <a href="{{ btn.url }}" target="_blank"
class="p-2 m-1 flex-1 border rounded bg-white border-blue-500 text-center text-blue-500 hover:bg-blue-500 hover:text-white transition ease-in duration-150"
> {{btn.text}} </a>
{% endfor %} {% endfor %}
</div> </div>
{% endfor %} {% endfor %}
@ -94,7 +96,9 @@
<div class="text-center text-white"> <div class="text-center text-white">
<a class="rounded p-3 bg-indigo-500 hover:bg-indigo-700 shadow-lg{% if block_downloads %} cursor-not-allowed disabled{% else %}" download="{{name}}{% endif %}" href="{{download_url}}">Download Now! ({{ human_size }})</a> <a href="{{download_url}}"
class="rounded p-3 bg-indigo-500 hover:bg-indigo-700 shadow-lg{% if block_downloads %} cursor-not-allowed disabled{% else %}" download="{{name}}{% endif %}"
>Download Now! ({{ human_size }})</a>
</div> </div>
{% else %} {% else %}
@ -107,7 +111,9 @@
{% for row in reply_btns %} {% for row in reply_btns %}
<div class="flex justify-center"> <div class="flex justify-center">
{% for btn in row %} {% for btn in row %}
<a class="p-2 m-1 flex-1 border rounded bg-white border-blue-500 text-center text-blue-500 hover:bg-blue-500 hover:text-white transition ease-in duration-150" href="{{btn.url}}" target="_blank"> {{btn.text}} </a> <a href="{{btn.url}}" target="_blank"
class="p-2 m-1 flex-1 border rounded bg-white border-blue-500 text-center text-blue-500 hover:bg-blue-500 hover:text-white transition ease-in duration-150"
> {{btn.text}} </a>
{% endfor %} {% endfor %}
</div> </div>
{% endfor %} {% endfor %}

2
app/templates/js/fluidplayer.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@ import aiohttp_jinja2
from aiohttp import web from aiohttp import web
from telethon.tl import types from telethon.tl import types
from telethon.tl.custom import Message from telethon.tl.custom import Message
from jinja2 import Markup from markupsafe import Markup
from app.util import get_file_name, get_human_size from app.util import get_file_name, get_human_size
from app.config import block_downloads from app.config import block_downloads