Compare commits
83 Commits
v0.1
...
f82c7b309f
Author | SHA1 | Date | |
---|---|---|---|
f82c7b309f | |||
399fc5050d | |||
56adb16a3e | |||
1684c5177c | |||
fba52bcfc4 | |||
20666fc0f8 | |||
03b6bbe039 | |||
1749d49a52 | |||
a4323981fb | |||
06b6b49f43 | |||
1f345e87f7 | |||
717586a9f0 | |||
95351f247c | |||
b5e3abd4ad | |||
4ec69c2a05 | |||
|
62e0a4986c | ||
|
be8f0262d0 | ||
|
ba5a0f116c | ||
|
e85adeafd0 | ||
87d2a2c6d3 | |||
bc6080e832 | |||
9bf4663b9e | |||
b74ce9ec89 | |||
6ed3673682 | |||
c593be156d | |||
c96f98560c | |||
e1c1b58ffb | |||
bd2a1f0b12 | |||
8cc7808afb | |||
6684c4d750 | |||
c670db72fa | |||
48acab2d5e | |||
62f076148c | |||
59b504e6d9 | |||
ad281ba981 | |||
0073120bf2 | |||
244173e556 | |||
98e9c5f5a2 | |||
a8545dd097 | |||
3f22340852 | |||
c2fb88ed65 | |||
88692ebc85 | |||
4331af415e | |||
a913ba19c6 | |||
2387823151 | |||
88f8bb4a52 | |||
cf6c1f03d7 | |||
0a309a9f59 | |||
7810f3b7b9 | |||
7b2534012d | |||
6e8b47cf4b | |||
c27b1c5a5b | |||
c7228a006b | |||
64ae3fb047 | |||
|
056fc52353 | ||
|
8bafd0cb35 | ||
|
fd47217bad | ||
|
6b7b5c22f2 | ||
|
b3698cfa70 | ||
|
7607003f55 | ||
|
7918049f49 | ||
|
fcd59b7aca | ||
|
8c478072c6 | ||
|
b766d0c52c | ||
|
807e629ae7 | ||
|
87af9fd333 | ||
|
a54081a2ae | ||
|
664284a6f8 | ||
|
bd9917fb17 | ||
|
68ea087963 | ||
|
d1813856d9 | ||
|
cf204577e4 | ||
|
68c887999e | ||
|
642e17ee55 | ||
|
25af9b31f8 | ||
|
28fc359593 | ||
|
07203a9db9 | ||
|
663a7b0db8 | ||
|
0d2e9fa6ec | ||
|
c90e5eb697 | ||
|
f4359aa6cd | ||
4cd37be5dc | |||
05042f01c6 |
20
.renovaterc
20
.renovaterc
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
||||||
"extends": [
|
|
||||||
"config:base"
|
|
||||||
],
|
|
||||||
"baseBranches": [
|
|
||||||
"dev"
|
|
||||||
],
|
|
||||||
"packageRules": [
|
|
||||||
{
|
|
||||||
"matchUpdateTypes": [
|
|
||||||
"minor",
|
|
||||||
"patch",
|
|
||||||
"pin",
|
|
||||||
"digest"
|
|
||||||
],
|
|
||||||
"automerge": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
15
README.md
15
README.md
@@ -50,7 +50,12 @@ To make this bot run at first you need to have a Python interpreter, Photos API,
|
|||||||
`python -m pip install -r requirements.txt`
|
`python -m pip install -r requirements.txt`
|
||||||
Without installing those - bot cannot work at all.
|
Without installing those - bot cannot work at all.
|
||||||
|
|
||||||
5. Configure "bot" and "owner" with your favorite text editor:
|
5. Install optional dependencies [Optional]:
|
||||||
|
|
||||||
|
`python -m pip install -r requirements-optional.txt`
|
||||||
|
These are not required but can make the bot run a bit faster.
|
||||||
|
|
||||||
|
6. Configure "bot" and "owner" with your favorite text editor:
|
||||||
|
|
||||||
1. Copy file `config_example.json` to `config.json`
|
1. Copy file `config_example.json` to `config.json`
|
||||||
2. Open `config.json` using your favorite text editor. For example `nano config.json`, but you can edit with vim, nano, on Windows it's Notepad or Notepad++. Whatever
|
2. Open `config.json` using your favorite text editor. For example `nano config.json`, but you can edit with vim, nano, on Windows it's Notepad or Notepad++. Whatever
|
||||||
@@ -58,7 +63,7 @@ To make this bot run at first you need to have a Python interpreter, Photos API,
|
|||||||
|
|
||||||
If you don't know where to find bot_token and your id - here you can find some hints: [get bot token](https://www.siteguarding.com/en/how-to-get-telegram-bot-api-token), [get your id](https://www.alphr.com/telegram-find-user-id), [get api_hash and api_id](https://core.telegram.org/api/obtaining_api_id).
|
If you don't know where to find bot_token and your id - here you can find some hints: [get bot token](https://www.siteguarding.com/en/how-to-get-telegram-bot-api-token), [get your id](https://www.alphr.com/telegram-find-user-id), [get api_hash and api_id](https://core.telegram.org/api/obtaining_api_id).
|
||||||
|
|
||||||
6. Configure database and API:
|
7. Configure database and API:
|
||||||
|
|
||||||
1. Configure database:
|
1. Configure database:
|
||||||
1. Change database host and port in keys `"database.host"` and `"database.port"`. For default local installation those will be `127.0.0.1` and `27017` respectively
|
1. Change database host and port in keys `"database.host"` and `"database.port"`. For default local installation those will be `127.0.0.1` and `27017` respectively
|
||||||
@@ -69,15 +74,15 @@ To make this bot run at first you need to have a Python interpreter, Photos API,
|
|||||||
1. Change `"posting.api.address"` to the one your API servers uses
|
1. Change `"posting.api.address"` to the one your API servers uses
|
||||||
2. Run your bot using `python poster.py --create-user --create-album` to configure its new user and album. You can also use manual user and album creation described [in the wiki](https://git.end-play.xyz/profitroll/TelegramPoster/wiki/Configuring-API). You can also change username, password and album in`"posting.api"` to the user and album you have if you already have Photos API album and user set up. In that case you don't need to create a new one.
|
2. Run your bot using `python poster.py --create-user --create-album` to configure its new user and album. You can also use manual user and album creation described [in the wiki](https://git.end-play.xyz/profitroll/TelegramPoster/wiki/Configuring-API). You can also change username, password and album in`"posting.api"` to the user and album you have if you already have Photos API album and user set up. In that case you don't need to create a new one.
|
||||||
|
|
||||||
7. Add bot to the channel:
|
8. Add bot to the channel:
|
||||||
|
|
||||||
To use your bot of course you need to have a channel or group otherwise makes no sense to have such a bot. [Here](https://stackoverflow.com/a/33497769) you can find a quick guide how to add your bot to a channel. After that simply set `"posting.channel"` to your channel's ID.
|
To use your bot of course you need to have a channel or group otherwise makes no sense to have such a bot. [Here](https://stackoverflow.com/a/33497769) you can find a quick guide how to add your bot to a channel. After that simply set `"posting.channel"` to your channel's ID.
|
||||||
|
|
||||||
8. Configure posting time:
|
9. Configure posting time:
|
||||||
|
|
||||||
To make your bot post random content you need to configure `"posting.time"` with a list of "DD:MM" formatted strings or use `"posting.interval"` formatted as "XdXhXmXs". To use interval instead of selected time set `"posting.use_interval"` to `true`.
|
To make your bot post random content you need to configure `"posting.time"` with a list of "DD:MM" formatted strings or use `"posting.interval"` formatted as "XdXhXmXs". To use interval instead of selected time set `"posting.use_interval"` to `true`.
|
||||||
|
|
||||||
9. Good to go, run it!
|
10. Good to go, run it!
|
||||||
|
|
||||||
Make sure MongoDB and Photos API are running and use `python poster.py` to start it.
|
Make sure MongoDB and Photos API are running and use `python poster.py` to start it.
|
||||||
Or you can also use `.\start.bat` on Windows and `bash ./start.sh` on Linux.
|
Or you can also use `.\start.bat` on Windows and `bash ./start.sh` on Linux.
|
||||||
|
@@ -23,7 +23,6 @@
|
|||||||
"reports": {
|
"reports": {
|
||||||
"sent": false,
|
"sent": false,
|
||||||
"error": true,
|
"error": true,
|
||||||
"update": true,
|
|
||||||
"startup": true,
|
"startup": true,
|
||||||
"shutdown": true
|
"shutdown": true
|
||||||
},
|
},
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
# Updating your bot
|
|
@@ -59,8 +59,7 @@
|
|||||||
"remove_ignored": "No response, aborting removal.",
|
"remove_ignored": "No response, aborting removal.",
|
||||||
"remove_abort": "Removal aborted.",
|
"remove_abort": "Removal aborted.",
|
||||||
"remove_success": "Removed media with ID `{0}`.",
|
"remove_success": "Removed media with ID `{0}`.",
|
||||||
"remove_failure": "Could not remove media with ID `{0}`. Check if provided ID is correct and if it is - you can also check bot's log for details.",
|
"remove_failure": "Could not remove media with ID `{0}`. Check if provided ID is correct and if it is - you can also check bot's log for details."
|
||||||
"update_available": "**New version found**\nThere's a newer version of a bot found. You can update your bot to [{0}]({1}) using command line of your host.\n\n**Release notes**\n{2}\n\nRead more about updating you bot on the [wiki page](https://git.end-play.xyz/profitroll/TelegramPoster/wiki/Updating-Instance).\n\nPlease not that you can also disable this notification by editing `reports.update` key of the config."
|
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"sub_yes": "✅ Accept",
|
"sub_yes": "✅ Accept",
|
||||||
|
@@ -59,8 +59,7 @@
|
|||||||
"remove_ignored": "Немає відповіді, перериваємо видалення.",
|
"remove_ignored": "Немає відповіді, перериваємо видалення.",
|
||||||
"remove_abort": "Видалення перервано.",
|
"remove_abort": "Видалення перервано.",
|
||||||
"remove_success": "Видалено медіа з ID `{0}`.",
|
"remove_success": "Видалено медіа з ID `{0}`.",
|
||||||
"remove_failure": "Не вдалося видалити медіа з ID `{0}`. Перевірте, чи вказано правильний ID, і якщо він правильний, ви також можете переглянути логи бота для отримання більш детальної інформації.",
|
"remove_failure": "Не вдалося видалити медіа з ID `{0}`. Перевірте, чи вказано правильний ID, і якщо він правильний, ви також можете переглянути логи бота для отримання більш детальної інформації."
|
||||||
"update_available": "**Знайдено нову версію**\nЗнайдено нову версію бота. Ви можете оновити бота до [{0}]({1}) за допомогою командного рядка вашого хосту.\n\n**Примітки до релізу**\n{2}\n\nДетальніше про оновлення бота можна знайти на [вікі-сторінці](https://git.end-play.xyz/profitroll/TelegramPoster/wiki/Updating-Instance).\n\nЗверніть увагу, що ви також можете вимкнути це сповіщення, відредагувавши ключ `reports.update` у конфігурації."
|
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"sub_yes": "✅ Прийняти",
|
"sub_yes": "✅ Прийняти",
|
||||||
|
@@ -8,7 +8,8 @@ from traceback import print_exc
|
|||||||
from typing import Tuple, Union
|
from typing import Tuple, Union
|
||||||
|
|
||||||
import aiofiles
|
import aiofiles
|
||||||
from aiohttp import FormData
|
from aiohttp import ClientSession, FormData
|
||||||
|
from ujson import dumps
|
||||||
|
|
||||||
from classes.exceptions import (
|
from classes.exceptions import (
|
||||||
AlbumCreationDuplicateError,
|
AlbumCreationDuplicateError,
|
||||||
@@ -20,7 +21,10 @@ from classes.exceptions import (
|
|||||||
)
|
)
|
||||||
from modules.logger import logWrite
|
from modules.logger import logWrite
|
||||||
from modules.utils import configGet, locale
|
from modules.utils import configGet, locale
|
||||||
from modules.http_client import http_session
|
|
||||||
|
http_session = ClientSession(
|
||||||
|
json_serialize=dumps,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def authorize() -> str:
|
async def authorize() -> str:
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
from aiohttp import ClientSession
|
|
||||||
from ujson import dumps
|
|
||||||
|
|
||||||
http_session = ClientSession(
|
|
||||||
json_serialize=dumps,
|
|
||||||
)
|
|
102
poster.py
102
poster.py
@@ -1,21 +1,18 @@
|
|||||||
from datetime import datetime
|
|
||||||
from os import getpid, path
|
from os import getpid, path
|
||||||
|
from datetime import datetime
|
||||||
from sys import exit
|
from sys import exit
|
||||||
from time import time
|
from time import time
|
||||||
from traceback import format_exc
|
|
||||||
from modules.api_client import authorize
|
|
||||||
|
|
||||||
from modules.cli import *
|
from modules.cli import *
|
||||||
from modules.http_client import http_session
|
|
||||||
from modules.logger import logWrite
|
from modules.logger import logWrite
|
||||||
from modules.scheduler import scheduler
|
from modules.scheduler import scheduler
|
||||||
from modules.utils import configGet, jsonLoad, jsonSave, locale
|
from modules.utils import configGet, jsonLoad, jsonSave, killProc, locale
|
||||||
|
|
||||||
# Import ===================================================================================================================================
|
# Import ===================================================================================================================================
|
||||||
try:
|
try:
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
from pyrogram.errors import bad_request_400
|
|
||||||
from pyrogram.sync import idle
|
from pyrogram.sync import idle
|
||||||
|
from pyrogram.errors import bad_request_400
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
from modules.app import app
|
from modules.app import app
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
@@ -25,7 +22,6 @@ except ModuleNotFoundError:
|
|||||||
|
|
||||||
|
|
||||||
pid = getpid()
|
pid = getpid()
|
||||||
version = 0.1
|
|
||||||
|
|
||||||
# Work in progress
|
# Work in progress
|
||||||
# def check_forwards(app):
|
# def check_forwards(app):
|
||||||
@@ -63,10 +59,9 @@ version = 0.1
|
|||||||
# check_forwards(app)
|
# check_forwards(app)
|
||||||
|
|
||||||
|
|
||||||
from plugins.callbacks.shutdown import *
|
|
||||||
|
|
||||||
# Imports ==================================================================================================================================
|
# Imports ==================================================================================================================================
|
||||||
from plugins.commands.general import *
|
from plugins.commands.general import *
|
||||||
|
from plugins.callbacks.shutdown import *
|
||||||
|
|
||||||
if configGet("submit", "mode"):
|
if configGet("submit", "mode"):
|
||||||
from plugins.callbacks.nothing import *
|
from plugins.callbacks.nothing import *
|
||||||
@@ -121,11 +116,10 @@ if configGet("post", "mode"):
|
|||||||
# uvloop.install()
|
# uvloop.install()
|
||||||
# asyncio.run(main())
|
# asyncio.run(main())
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
async def main():
|
|
||||||
logWrite(locale("startup", "console").format(str(pid)))
|
logWrite(locale("startup", "console").format(str(pid)))
|
||||||
|
|
||||||
await app.start()
|
app.start()
|
||||||
|
|
||||||
if configGet("startup", "reports"):
|
if configGet("startup", "reports"):
|
||||||
try:
|
try:
|
||||||
@@ -139,7 +133,7 @@ async def main():
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
if downtime.days >= 1:
|
if downtime.days >= 1:
|
||||||
await app.send_message(
|
app.send_message(
|
||||||
configGet("owner"),
|
configGet("owner"),
|
||||||
locale(
|
locale(
|
||||||
"startup_downtime_days",
|
"startup_downtime_days",
|
||||||
@@ -147,7 +141,7 @@ async def main():
|
|||||||
).format(pid, downtime.days),
|
).format(pid, downtime.days),
|
||||||
)
|
)
|
||||||
elif downtime.hours >= 1:
|
elif downtime.hours >= 1:
|
||||||
await app.send_message(
|
app.send_message(
|
||||||
configGet("owner"),
|
configGet("owner"),
|
||||||
locale(
|
locale(
|
||||||
"startup_downtime_hours",
|
"startup_downtime_hours",
|
||||||
@@ -155,7 +149,7 @@ async def main():
|
|||||||
).format(pid, downtime.hours),
|
).format(pid, downtime.hours),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await app.send_message(
|
app.send_message(
|
||||||
configGet("owner"),
|
configGet("owner"),
|
||||||
locale(
|
locale(
|
||||||
"startup_downtime_minutes",
|
"startup_downtime_minutes",
|
||||||
@@ -164,7 +158,7 @@ async def main():
|
|||||||
).format(pid, downtime.minutes),
|
).format(pid, downtime.minutes),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await app.send_message(
|
app.send_message(
|
||||||
configGet("owner"),
|
configGet("owner"),
|
||||||
locale("startup", "message").format(pid),
|
locale("startup", "message").format(pid),
|
||||||
)
|
)
|
||||||
@@ -173,75 +167,18 @@ async def main():
|
|||||||
f"Could not send startup message to bot owner. Perhaps user has not started the bot yet."
|
f"Could not send startup message to bot owner. Perhaps user has not started the bot yet."
|
||||||
)
|
)
|
||||||
|
|
||||||
if configGet("update", "reports"):
|
|
||||||
try:
|
|
||||||
check_update = await http_session.get(
|
|
||||||
"https://git.end-play.xyz/api/v1/repos/profitroll/TelegramPoster/releases?page=1&limit=1"
|
|
||||||
)
|
|
||||||
response = await check_update.json()
|
|
||||||
if len(response) == 0:
|
|
||||||
raise ValueError("No bot releases on git found.")
|
|
||||||
if float(response[0]["tag_name"].replace("v.", "")) > version:
|
|
||||||
logWrite(
|
|
||||||
f'New version {response[0]["tag_name"].replace("v.", "")} found (current {version})'
|
|
||||||
)
|
|
||||||
await app.send_message(
|
|
||||||
configGet("owner"),
|
|
||||||
locale(
|
|
||||||
"update_available",
|
|
||||||
"message",
|
|
||||||
).format(
|
|
||||||
response[0]["tag_name"],
|
|
||||||
response[0]["html_url"],
|
|
||||||
response[0]["body"],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
logWrite(f"No updates found, bot is up to date.")
|
|
||||||
except bad_request_400.PeerIdInvalid:
|
|
||||||
logWrite(
|
|
||||||
f"Could not send startup message to bot owner. Perhaps user has not started the bot yet."
|
|
||||||
)
|
|
||||||
except Exception as exp:
|
|
||||||
logWrite(f"Update check failed due to {exp}: {format_exc()}")
|
|
||||||
|
|
||||||
if configGet("post", "mode"):
|
if configGet("post", "mode"):
|
||||||
scheduler.start()
|
scheduler.start()
|
||||||
|
|
||||||
try:
|
# if configGet("api_based", "mode"):
|
||||||
token = await authorize()
|
# token = await authorize()
|
||||||
|
# if len(get(f'{configGet("address", "posting", "api")}/albums?q={configGet("queue", "posting", "api", "albums")}', headers={"Authorization": f"Bearer {token}"}).json()["results"]) == 0:
|
||||||
|
# post(f'{configGet("address", "posting", "api")}/albums?name={configGet("queue", "posting", "api", "albums")}&title={configGet("queue", "posting", "api", "albums")}', headers={"Authorization": f"Bearer {token}"})
|
||||||
|
|
||||||
if (
|
idle()
|
||||||
len(
|
|
||||||
(
|
|
||||||
await (
|
|
||||||
await http_session.get(
|
|
||||||
f'{configGet("address", "posting", "api")}/albums?q={configGet("album", "posting", "api")}',
|
|
||||||
headers={"Authorization": f"Bearer {token}"},
|
|
||||||
)
|
|
||||||
).json()
|
|
||||||
)["results"]
|
|
||||||
)
|
|
||||||
== 0
|
|
||||||
):
|
|
||||||
logWrite("Media album does not exist on API server. Trying to create it...")
|
|
||||||
try:
|
|
||||||
await http_session.post(
|
|
||||||
f'{configGet("address", "posting", "api")}/albums?name={configGet("album", "posting", "api")}&title={configGet("album", "posting", "api")}',
|
|
||||||
headers={"Authorization": f"Bearer {token}"},
|
|
||||||
)
|
|
||||||
logWrite("Created media album on API server.")
|
|
||||||
except Exception as exp:
|
|
||||||
logWrite(
|
|
||||||
f"Could not create media album on API server due to {exp}: {format_exc()}"
|
|
||||||
)
|
|
||||||
except Exception as exp:
|
|
||||||
logWrite(f"Could not check if API album exists due to {exp}: {format_exc()}")
|
|
||||||
|
|
||||||
await idle()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await app.send_message(
|
app.send_message(
|
||||||
configGet("owner"),
|
configGet("owner"),
|
||||||
locale("shutdown", "message").format(pid),
|
locale("shutdown", "message").format(pid),
|
||||||
)
|
)
|
||||||
@@ -260,7 +197,4 @@ async def main():
|
|||||||
|
|
||||||
scheduler.shutdown()
|
scheduler.shutdown()
|
||||||
|
|
||||||
|
killProc(pid)
|
||||||
if __name__ == "__main__":
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.run_until_complete(main())
|
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
tgcrypto==1.2.5
|
@@ -1,12 +1,11 @@
|
|||||||
python_dateutil==2.8.2
|
python_dateutil==2.8.2
|
||||||
apscheduler==3.10.1
|
apscheduler~=3.10.1
|
||||||
pytimeparse==1.1.8
|
pytimeparse~=1.1.8
|
||||||
convopyro==0.5
|
convopyro==0.5
|
||||||
pyrogram==2.0.104
|
pyrogram~=2.0.102
|
||||||
aiofiles~=23.1.0
|
aiofiles~=23.1.0
|
||||||
tgcrypto==1.2.5
|
|
||||||
aiohttp~=3.8.4
|
aiohttp~=3.8.4
|
||||||
psutil==5.9.5
|
psutil~=5.9.4
|
||||||
pymongo==4.3.3
|
pymongo~=4.3.3
|
||||||
pillow~=9.5.0
|
pillow~=9.4.0
|
||||||
ujson==5.7.0
|
ujson~=5.7.0
|
Reference in New Issue
Block a user