Skip to content

Commit

Permalink
Added Broadcasting Feature
Browse files Browse the repository at this point in the history
Users in the 'SUDO_USERS' list can broadcast messages to the bot users. Also they can access the subs count. If the 'AUTH_USERS' list is empty, the bot can be used by publicly.
  • Loading branch information
m4mallu committed Aug 13, 2021
1 parent 377f823 commit e0390d2
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 8 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,23 @@
</a>
</p>

## [@BotFather](https://t.me/botfather) Commands

* `start - Check alive`
* `send - broadcast` (As a reply to any message)
* `subs - Count active subscribers`

## Mandatory Variables

* `API_HASH` Your API Hash from my.telegram.org
* `API_ID` Your API ID from my.telegram.org
* `BOT_TOKEN` Your bot token from @BotFather
* `AUTH_USERS` Create a list of User Ids to use this bot
* `BOT_TOKEN` Your bot token from @BotFather.
* `AUTH_USERS` Create a list of User Ids to use this bot. (If kept empty, bot will be in public domain)
* `SUDO_USERS` Create a list of Super User Ids to use this bot. (For Broadcasting )
* `DB_URI` (Mandatory when deployed in local)

## Deploy Locally
Create a database URI with the [TUTORIAL](https://telegra.ph/Clonebot-UI-Help-05-30)

Create a `config.py` with the above variables (Refer sample_config.py)
```
Expand Down
9 changes: 9 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@
"API_HASH": {"description": "Get this value from https://my.telegram.org" , "required": true},
"TG_BOT_TOKEN": {"description": "Get Bot Token From @BotFather Bot", "required": true},
"AUTH_USERS": {"description": "List of Authorized user ids separated by space", "required": false},
"SUDO_USERS": {"description": "List of super user ids for broadcast. separated by space", "required": true},
"ENV": {"description": "Set this to ANYTHING","value": "ANYTHING"}
},
"addons": [
{
"plan": "heroku-postgresql",
"options": {
"version": "12"
}
}
],
"buildpacks": [
{
"url": "heroku/python"
Expand Down
12 changes: 12 additions & 0 deletions library/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
],
[
InlineKeyboardButton('Help', callback_data='help_btn'),
InlineKeyboardButton('Support', url='t.me/RMProjects')
],
[
InlineKeyboardButton('Close', callback_data='close_btn'),
InlineKeyboardButton('Search Inline', switch_inline_query_current_chat='')
]
]
Expand Down Expand Up @@ -55,12 +59,20 @@
]
]

prompt_thumb_btn = [
[
InlineKeyboardButton('Yes', callback_data='set_thumb_btn'),
InlineKeyboardButton('No', callback_data='close_btn')
]
]

reply_markup_cancel = InlineKeyboardMarkup(cancel_button)
reply_markup_close = InlineKeyboardMarkup(close_button)
reply_markup_back = InlineKeyboardMarkup(back_button)
reply_markup_join = InlineKeyboardMarkup(join_channel)
reply_markup_del_thumb = InlineKeyboardMarkup(del_thumb)
reply_markup_start = InlineKeyboardMarkup(start_btn)
reply_markup_thumb = InlineKeyboardMarkup(prompt_thumb_btn)

def get_reply_markup(username):
url = 't.me/share/url?url=' + quote(Presets.SHARE_BUTTON_TEXT.format(username=username))
Expand Down
60 changes: 60 additions & 0 deletions library/sql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name : inline-tube-mate [ Telegram ]
# Repo : https://github.com/m4mallu/inine-tube-mate
# Author : Renjith Mangal [ https://t.me/space4renjith ]
# Credits : https://github.com/SpEcHiDe/AnyDLBot

import os
import threading
from sqlalchemy import create_engine
from sqlalchemy import Column, TEXT, Numeric
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session


if bool(os.environ.get("ENV", False)):
from sample_config import Config
else:
from config import Config


def start() -> scoped_session:
engine = create_engine(Config.DB_URI, client_encoding="utf8")
BASE.metadata.bind = engine
BASE.metadata.create_all(engine)
return scoped_session(sessionmaker(bind=engine, autoflush=False))


BASE = declarative_base()
SESSION = start()

INSERTION_LOCK = threading.RLock()

class Ytdl(BASE):
__tablename__ = "ytdl"
id = Column(Numeric, primary_key=True)

def __init__(self, id):
self.id = id

Ytdl.__table__.create(checkfirst=True)


# ------------------------------------ Add user details ----------------------------- #
async def add_user(id):
with INSERTION_LOCK:
msg = SESSION.query(Ytdl).get(id)
if not msg:
usr = Ytdl(id)
SESSION.add(usr)
SESSION.commit()
else:
pass

async def query_msg():
try:
query = SESSION.query(Ytdl.id).order_by(Ytdl.id)
return query
finally:
SESSION.close()
29 changes: 29 additions & 0 deletions library/support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# Name : inline-tube-mate [ Telegram ]
# Repo : https://github.com/m4mallu/inine-tube-mate
# Author : Renjith Mangal [ https://t.me/space4renjith ]
# Credits : https://github.com/SpEcHiDe/AnyDLBot

import asyncio
from library.sql import query_msg
from pyrogram.errors import FloodWait


async def users_info(bot):
users = 0
blocked = 0
identity = await query_msg()
for id in identity:
name = bool()
try:
name = await bot.send_chat_action(int(id[0]), "typing")
except FloodWait as e:
await asyncio.sleep(e.x)
except Exception:
pass
if bool(name):
users += 1
else:
blocked += 1
return users, blocked
12 changes: 11 additions & 1 deletion plugins/callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pyrogram.types import CallbackQuery
from library.display_progress import cancel_process
from plugins.youtube_dl_button import youtube_dl_call_back
from library.buttons import reply_markup_del_thumb, reply_markup_start, reply_markup_back
from library.buttons import reply_markup_del_thumb, reply_markup_start, reply_markup_back, reply_markup_close


if bool(os.environ.get("ENV", False)):
Expand Down Expand Up @@ -114,7 +114,17 @@ async def cancel_upload_process(bot, cb: CallbackQuery):
await cb.message.delete()


@Client.on_callback_query(filters.regex(r'^set_thumb_btn$'))
async def set_thumb(bot, cb: CallbackQuery):
await cb.message.edit(Presets.DOWNLOAD_START)
thumb_image = os.getcwd() + "/" + "thumbnails" + "/" + str(cb.from_user.id) + ".jpg"
message = cb.message.reply_to_message
await bot.download_media(message, thumb_image)
await cb.message.edit_text(Presets.SAVED_THUMB, reply_markup=reply_markup_close)


@Client.on_callback_query()
async def Youtube_dl_button(bot, cb: CallbackQuery):
if "|" in cb.data:
await youtube_dl_call_back(bot, cb)
await youtube_dl_call_back(bot, cb)
60 changes: 59 additions & 1 deletion plugins/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,70 @@
# Repo : https://github.com/m4mallu/inine-tube-mate
# Author : Renjith Mangal [ https://t.me/space4renjith ]

import os
import asyncio
from presets import Presets
from pyrogram.types import Message
from pyrogram import Client, filters
from library.buttons import reply_markup_start
from pyrogram.errors import FloodWait
from library.support import users_info
from library.sql import add_user, query_msg
from library.buttons import reply_markup_start, reply_markup_close


if bool(os.environ.get("ENV", False)):
from sample_config import Config
else:
from config import Config


@Client.on_message(filters.private & filters.command(['start', 'help']))
async def start_bot(bot, m: Message):
await add_user(m.from_user.id)
await m.reply_text(Presets.WELCOME_MSG.format(m.from_user.first_name),
reply_markup=reply_markup_start)


@Client.on_message(filters.private & filters.command('send'))
async def send_messages(bot, m: Message):
if m.from_user.id not in Config.SUDO_USERS:
return
msg = await m.reply_text(Presets.SEND_TEXT)
await m.delete()
if m.reply_to_message is not None:
query = await query_msg()
for row in query:
chat_id = int(row[0])
try:
await bot.copy_message(
chat_id=chat_id,
from_chat_id=m.chat.id,
message_id=m.reply_to_message.message_id,
caption=m.caption
)
except FloodWait as e:
await asyncio.sleep(e.x)
except Exception:
pass
await msg.delete()
else:
await m.delete()
await m.reply_text(Presets.REPLY_ERROR,
m.message_id,
reply_markup=reply_markup_close
)


@Client.on_message(filters.private & filters.command('subs'))
async def subscribers_count(bot, m: Message):
id = m.from_user.id
if id not in Config.SUDO_USERS:
return
msg = await m.reply_text(Presets.WAIT_MSG)
await m.delete()
messages = await users_info(bot)
active = messages[0]
blocked = messages[1]
total = active + blocked
await msg.edit(Presets.USERS_LIST.format(total, active, blocked),
reply_markup=reply_markup_close)
2 changes: 2 additions & 0 deletions plugins/inline.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import asyncio
from pyrogram import Client
from presets import Presets
from library.sql import add_user
from library.info import get_info
from pyrogram.errors import FloodWait
from library.extract import youtube_search
Expand All @@ -22,6 +23,7 @@

@Client.on_inline_query()
async def inline_search(bot, query: InlineQuery):
await add_user(query.from_user.id)
me = []
try:
me = await Client.get_me(bot)
Expand Down
8 changes: 5 additions & 3 deletions plugins/thumbail.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from presets import Presets
from pyrogram.types import Message
from pyrogram import Client, filters
from library.buttons import reply_markup_thumb, reply_markup_close


if bool(os.environ.get("ENV", False)):
Expand All @@ -21,6 +22,9 @@
@Client.on_message(filters.private & filters.photo)
async def save_photo(bot, m: Message):
msg = await m.reply_text(Presets.WAIT_MESSAGE, reply_to_message_id=m.message_id)
if m.from_user.id in Config.SUDO_USERS:
await msg.edit(Presets.PROMPT_THUMB, reply_markup=reply_markup_thumb)
return
if Config.AUTH_USERS and (m.from_user.id not in Config.AUTH_USERS):
await m.delete()
await msg.edit_text(Presets.NOT_AUTH_TXT)
Expand All @@ -29,6 +33,4 @@ async def save_photo(bot, m: Message):
return
thumb_image = os.getcwd() + "/" + "thumbnails" + "/" + str(m.from_user.id) + ".jpg"
await bot.download_media(m, thumb_image)
await msg.edit_text(Presets.SAVED_THUMB)
await asyncio.sleep(5)
await msg.delete()
await msg.edit_text(Presets.SAVED_THUMB, reply_markup=reply_markup_close)
7 changes: 6 additions & 1 deletion presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ class Presets(object):
UPLOAD_START = "𝐔𝐩𝐥𝐨𝐚𝐝𝐢𝐧𝐠 𝐭𝐨 𝐓𝐞𝐥𝐞𝐠𝐫𝐚𝐦..."
NOT_DOWNLOADABLE = "𝐔𝐑𝐋 𝐍𝐨𝐭 𝐝𝐨𝐰𝐧𝐥𝐨𝐚𝐝𝐚𝐛𝐥𝐞 !"
CANCEL_PROCESS = "<b>Process Cancelled Successfully</b> ✅"
SEND_TEXT = "<b>Processing...</b>\n<i>This message will automatically disappear when the broadcasting is finished</i> "
REPLY_ERROR = "<i>Use this command as a replay to any telegram message with out any spaces.</i>"
USERS_LIST = "<b>Total: {}</b>\n\nSubscribers - {}\nBlocked / Deleted - {}"
WAIT_MSG = "<b>Processing...</b>\n<i>This will take some time...</i>"
PROMPT_THUMB = "<b>Do you want to set this image as a thumbnail?</b>"
FORMAT_SELECTION = """
<b>Title -</b> {}
<b>Channel -</b> <a href={}>{}</a>
Expand All @@ -56,7 +61,7 @@ class Presets(object):
"""
SET_CUSTOM_USERNAME_PASSWORD = """If you want to download premium videos, provide in the following format:
URL | newfilename | username | password"""
CUSTOM_CAPTION_UL_FILE = "\xad \xad\n<code>{}</code>\n\n<b>A project of:</b>\n<b><a href='https://t.me/RMProjects'>@RMProjects</a></b>"
CUSTOM_CAPTION_UL_FILE = "\xad \xad\n<code>{}</code>\n\n<b>Credits- </b><b><a href='https://t.me/RMProjects'>@RMProjects</a></b>"
RCHD_TG_API_LIMIT = "Detected File Size: {}\nSorry. But, I cannot upload files " \
"greater than 1.95GB due to Telegram API limitations."
AD_STRING_TO_REPLACE = "please report this issue on https://yt-dl.org/bug . Make sure you are using the " \
Expand Down
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ youtube-search-python
youtube-dl
hachoir
wget
# --- Database ---------------- #
sqlalchemy~=1.3.23
psycopg2-binary
feedparser
6 changes: 6 additions & 0 deletions sample_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ class Config(object):
# Authorized user ids to use this bot
AUTH_USERS = set(int(x) for x in os.environ.get("AUTH_USERS", "").split())

# Super users to broadcast messages & fetch subscribers count
SUDO_USERS = set(int(x) for x in os.environ.get("AUTH_USERS", "").split())

# Database URI
DB_URI = os.environ.get("DATABASE_URL", "")

# proxy for accessing youtube-dl in GeoRestricted Areas
# Get your own proxy from https://github.com/rg3/youtube-dl/issues/1091#issuecomment-230163061
HTTP_PROXY = os.environ.get("HTTP_PROXY", "")
Expand Down

0 comments on commit e0390d2

Please sign in to comment.