more flexible indexing
This commit is contained in:
parent
d014abb73f
commit
b1f1199b76
36
README.md
36
README.md
|
@ -14,14 +14,14 @@ Hosted demo site: https://tg-index-demo.herokuapp.com/
|
|||
|
||||
## Deploy Guide
|
||||
|
||||
* Clone to local machine.
|
||||
* **Clone to local machine.**
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/odysseusmax/tg-index.git
|
||||
$ cd tg-index
|
||||
```
|
||||
|
||||
* Create and activate virtual environment.
|
||||
* **Create and activate virtual environment.**
|
||||
|
||||
```bash
|
||||
$ pip3 install virtualenv
|
||||
|
@ -29,25 +29,47 @@ $ virtualenv venv
|
|||
$ source venv/bin/activate
|
||||
```
|
||||
|
||||
* Install dependencies.
|
||||
* **Install dependencies.**
|
||||
|
||||
```bash
|
||||
$ 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_HASH` (required) | Telegram api_hash obtained from https://my.telegram.org/apps.
|
||||
| `CHAT_ID` (required) | Id of the telegram channel (or chat) to be indexed. Separate id's with space if you want to index more than one channel.
|
||||
| `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.
|
||||
| `HOST` (optional) | Host name on which app should listen to, defaults to 0.0.0.0.
|
||||
| `DEBUG` (optional) | Give some value to set logging level to debug, info by default.
|
||||
|
||||
* Run app.
|
||||
* **Setting value for `INDEX_SETTINGS`**
|
||||
|
||||
This is the general format, change the values for corresponding fields as your requirements.
|
||||
|
||||
```
|
||||
{
|
||||
"index_all": true,
|
||||
"index_private":false,
|
||||
"index_group": false,
|
||||
"index_channel": true,
|
||||
"exclude_chats": []
|
||||
"include_chats": [],
|
||||
}
|
||||
```
|
||||
* `index_all` - Whether to consider all the chats associated with the telegram account. Value should either be `true` or `false`.
|
||||
* `index_private` - Whether to index private chats. Only considered if `index_all` is set to `true`. Value should either be `true` or `false`.
|
||||
* `index_group` - Whether to index group chats. Only considered if `index_all` is set to `true`. Value should either be `true` or `false`.
|
||||
* `index_channel` - Whether to index channels. Only considered if `index_all` is set to `true`. Value should either be `true` or `false`.
|
||||
* `exclude_chats` - An array/list of chat id's that should be ignored for indexing. Only considered if `index_all` is set to `true`.
|
||||
* `include_chats` - An array/list of chat id's to index. Only considered if `index_all` is set to `false`.
|
||||
|
||||
|
||||
* **Run app.**
|
||||
|
||||
```bash
|
||||
$ python3 -m app
|
||||
|
|
4
app.json
4
app.json
|
@ -12,8 +12,8 @@
|
|||
"description":"Telegram api_hash obtained from https://my.telegram.org/apps.",
|
||||
"value":""
|
||||
},
|
||||
"CHAT_ID":{
|
||||
"description":"Id of the telegram channel (or chat) to be indexed. Separate id's with space if you want to index more than one channel.",
|
||||
"INDEX_SETTINGS":{
|
||||
"description":"Refer project docs for info.",
|
||||
"value": ""
|
||||
},
|
||||
"SESSION_STRING":{
|
||||
|
|
|
@ -38,7 +38,7 @@ async def stop(app):
|
|||
async def init():
|
||||
server = web.Application()
|
||||
await start()
|
||||
setup_routes(server, Views(client))
|
||||
await setup_routes(server, Views(client))
|
||||
setup_jinja(server)
|
||||
server.on_cleanup.append(stop)
|
||||
return server
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import traceback
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
@ -21,12 +22,15 @@ except (KeyError, ValueError):
|
|||
sys.exit(1)
|
||||
|
||||
try:
|
||||
chat_id_raw = os.environ["CHAT_ID"].strip()
|
||||
chat_ids = [int(chat_id.strip()) for chat_id in chat_id_raw.split(' ')]
|
||||
alias_ids = []
|
||||
except (KeyError, ValueError):
|
||||
index_settings_str = os.environ["INDEX_SETTINGS"].strip()
|
||||
index_settings = json.loads(index_settings_str)
|
||||
'''
|
||||
{"index_all": true, "index_private":false, "index_group": false, "index_channel": true, "include_chats": [], "exclude_chats": []}
|
||||
|
||||
'''
|
||||
except:
|
||||
traceback.print_exc()
|
||||
print("\n\nPlease set the CHAT_ID environment variable correctly")
|
||||
print("\n\nPlease set the INDEX_SETTINGS environment variable correctly")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
|
@ -38,3 +42,5 @@ except (KeyError, ValueError):
|
|||
|
||||
host = os.environ.get("HOST", "0.0.0.0")
|
||||
debug = bool(os.environ.get("DEBUG"))
|
||||
chat_ids = []
|
||||
alias_ids = []
|
||||
|
|
|
@ -1,23 +1,62 @@
|
|||
import random
|
||||
import string
|
||||
import logging
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
from .config import chat_ids, alias_ids
|
||||
from .config import index_settings, alias_ids, chat_ids
|
||||
|
||||
|
||||
def setup_routes(app, handler):
|
||||
h = handler
|
||||
routes = [
|
||||
web.get('/', h.home, name='home')
|
||||
]
|
||||
for chat_id in chat_ids:
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def generate_alias_id(chat):
|
||||
chat_id = chat.id
|
||||
title = chat.title
|
||||
while True:
|
||||
alias_id = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(len(str(chat_id)))])
|
||||
if alias_id in alias_ids:
|
||||
continue
|
||||
alias_ids.append(alias_id)
|
||||
break
|
||||
chat_ids.append({
|
||||
'chat_id': chat_id,
|
||||
'alias_id': alias_id,
|
||||
'title': title
|
||||
})
|
||||
return alias_id
|
||||
|
||||
|
||||
async def setup_routes(app, handler):
|
||||
h = handler
|
||||
client = h.client
|
||||
routes = [
|
||||
web.get('/', h.home, name='home')
|
||||
]
|
||||
index_all = index_settings['index_all']
|
||||
index_private = index_settings['index_private']
|
||||
index_group = index_settings['index_group']
|
||||
index_channel = index_settings['index_channel']
|
||||
exclude_chats = index_settings['exclude_chats']
|
||||
include_chats = index_settings['include_chats']
|
||||
if index_all:
|
||||
async for chat in client.iter_dialogs():
|
||||
alias_id = None
|
||||
if chat.id in exclude_chats:
|
||||
continue
|
||||
|
||||
if chat.is_user:
|
||||
if index_private:
|
||||
alias_id = generate_alias_id(chat)
|
||||
elif chat.is_group:
|
||||
if index_group:
|
||||
alias_id = generate_alias_id(chat)
|
||||
else:
|
||||
if index_channel:
|
||||
alias_id = generate_alias_id(chat)
|
||||
|
||||
if not alias_id:
|
||||
continue
|
||||
|
||||
p = f"/{alias_id}"
|
||||
r = [
|
||||
web.get(p, h.index),
|
||||
|
@ -29,4 +68,21 @@ def setup_routes(app, handler):
|
|||
web.head(p + r"/{id:\d+}/thumbnail", h.thumbnail_head),
|
||||
]
|
||||
routes += r
|
||||
log.debug(f"Index added for {chat.id} :: {chat.title} at /{alias_id}")
|
||||
else:
|
||||
for chat_id in include_chats:
|
||||
chat = await client.get_entity(chat_id)
|
||||
alias_id = generate_alias_id(chat)
|
||||
p = f"/{alias_id}"
|
||||
r = [
|
||||
web.get(p, h.index),
|
||||
web.get(p + r"/logo", h.logo),
|
||||
web.get(p + r"/{id:\d+}/view", h.info),
|
||||
web.get(p + r"/{id:\d+}/download", h.download_get),
|
||||
web.head(p + r"/{id:\d+}/download", h.download_head),
|
||||
web.get(p + r"/{id:\d+}/thumbnail", h.thumbnail_get),
|
||||
web.head(p + r"/{id:\d+}/thumbnail", h.thumbnail_head),
|
||||
]
|
||||
routes += r
|
||||
log.debug(f"Index added for {chat.id} :: {chat.title} at /{alias_id}")
|
||||
app.add_routes(routes)
|
||||
|
|
28
app/views.py
28
app/views.py
|
@ -7,7 +7,7 @@ from telethon.tl import types
|
|||
from telethon.tl.custom import Message
|
||||
|
||||
from .util import get_file_name, get_human_size
|
||||
from .config import chat_ids, alias_ids
|
||||
from .config import index_settings, chat_ids
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -22,13 +22,12 @@ class Views:
|
|||
@aiohttp_jinja2.template('home.html')
|
||||
async def home(self, req):
|
||||
if len(chat_ids) == 1:
|
||||
raise web.HTTPFound(f"{alias_ids[0]}")
|
||||
raise web.HTTPFound(f"{chat_ids[0]['alias_id']}")
|
||||
chats = []
|
||||
for chat_id, alias_id in zip(chat_ids, alias_ids):
|
||||
chat = await self.client.get_entity(chat_id)
|
||||
for chat in chat_ids:
|
||||
chats.append({
|
||||
'id': alias_id,
|
||||
'name': chat.title
|
||||
'id': chat['alias_id'],
|
||||
'name': chat['title']
|
||||
})
|
||||
return {'chats':chats}
|
||||
|
||||
|
@ -36,8 +35,8 @@ class Views:
|
|||
@aiohttp_jinja2.template('index.html')
|
||||
async def index(self, req):
|
||||
alias_id = req.rel_url.path.split('/')[1]
|
||||
chat_id = chat_ids[alias_ids.index(alias_id)]
|
||||
chat = await self.client.get_entity(chat_id)
|
||||
chat = [i for i in chat_ids if i['alias_id'] == alias_id][0]
|
||||
chat_id = chat['chat_id']
|
||||
log_msg = ''
|
||||
try:
|
||||
offset_val = int(req.query.get('page', '1'))
|
||||
|
@ -67,6 +66,7 @@ class Views:
|
|||
log.debug(log_msg)
|
||||
results = []
|
||||
for m in messages:
|
||||
entry = None
|
||||
if m.file and not isinstance(m.media, types.MessageMediaWebPage):
|
||||
entry = dict(
|
||||
file_id=m.id,
|
||||
|
@ -87,6 +87,7 @@ class Views:
|
|||
size=get_human_size(len(m.raw_text)),
|
||||
url=req.rel_url.with_path(f"/{alias_id}/{m.id}/view")
|
||||
)
|
||||
if entry:
|
||||
results.append(entry)
|
||||
prev_page = False
|
||||
next_page = False
|
||||
|
@ -114,7 +115,7 @@ class Views:
|
|||
'cur_page' : offset_val+1,
|
||||
'next_page': next_page,
|
||||
'search': search_query,
|
||||
'name' : chat.title,
|
||||
'name' : chat['title'],
|
||||
'logo': req.rel_url.with_path(f"/{alias_id}/logo")
|
||||
}
|
||||
|
||||
|
@ -123,7 +124,8 @@ class Views:
|
|||
async def info(self, req):
|
||||
file_id = int(req.match_info["id"])
|
||||
alias_id = req.rel_url.path.split('/')[1]
|
||||
chat_id = chat_ids[alias_ids.index(alias_id)]
|
||||
chat = [i for i in chat_ids if i['alias_id'] == alias_id][0]
|
||||
chat_id = chat['chat_id']
|
||||
message = await self.client.get_messages(entity=chat_id, ids=file_id)
|
||||
if not message or not isinstance(message, Message):
|
||||
log.debug(f"no valid entry for {file_id} in {chat_id}")
|
||||
|
@ -191,7 +193,8 @@ class Views:
|
|||
|
||||
async def logo(self, req):
|
||||
alias_id = req.rel_url.path.split('/')[1]
|
||||
chat_id = chat_ids[alias_ids.index(alias_id)]
|
||||
chat = [i for i in chat_ids if i['alias_id'] == alias_id][0]
|
||||
chat_id = chat['chat_id']
|
||||
photo = await self.client.get_profile_photos(chat_id)
|
||||
if not photo:
|
||||
return web.Response(status=404, text="404: Chat has no profile photo")
|
||||
|
@ -231,7 +234,8 @@ class Views:
|
|||
async def handle_request(self, req, head=False, thumb=False):
|
||||
file_id = int(req.match_info["id"])
|
||||
alias_id = req.rel_url.path.split('/')[1]
|
||||
chat_id = chat_ids[alias_ids.index(alias_id)]
|
||||
chat = [i for i in chat_ids if i['alias_id'] == alias_id][0]
|
||||
chat_id = chat['chat_id']
|
||||
message = await self.client.get_messages(entity=chat_id, ids=file_id)
|
||||
if not message or not message.file:
|
||||
log.debug(f"no result for {file_id} in {chat_id}")
|
||||
|
|
Loading…
Reference in New Issue