3 Commits

Author SHA1 Message Date
853c3c7cea dev (#19)
* Config file changes
* Commands `/remove`, `/import` and `/export`

Co-authored-by: profitroll <vozhd.kk@gmail.com>
Co-authored-by: Profitroll <47523801+profitrollgame@users.noreply.github.com>
Co-authored-by: Renovate <renovate@git.end-play.xyz>
Reviewed-on: #19
2023-04-24 13:48:22 +03:00
e5f80d9702 Updated Renovate config 2023-04-20 13:41:14 +02:00
6f03d5c18f Configure Renovate (#14)
Welcome to [Renovate](https://github.com/renovatebot/renovate)! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin.

🚦 To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged.

---
### Detected Package Files

 * `requirements.txt` (pip_requirements)

### Configuration Summary

Based on the default config's presets, Renovate will:

  - Start dependency updates only once this onboarding PR is merged
  - Enable Renovate Dependency Dashboard creation.
  - Use semantic commit type `fix` for dependencies and `chore` for all others if semantic commits are in use.
  - Ignore `node_modules`, `bower_components`, `vendor` and various test/tests directories.
  - Group known monorepo packages together.
  - Use curated list of recommended non-monorepo package groupings.
  - Apply crowd-sourced package replacement rules.
  - Apply crowd-sourced workarounds for known problems with packages.

🔡 Would you like to change the way Renovate is upgrading your dependencies? Simply edit the `.renovaterc` in this branch with your custom config and the list of Pull Requests in the "What to Expect" section below will be updated the next time Renovate runs.

---

### What to Expect

It looks like your repository dependencies are already up-to-date and no Pull Requests will be necessary right away.

---

 Got questions? Check out Renovate's [Docs](https://docs.renovatebot.com/), particularly the Getting Started section.
If you need any further assistance then you can also [request help here](https://github.com/renovatebot/renovate/discussions).

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).

Reviewed-on: #14
Co-authored-by: Renovate <renovate@git.end-play.xyz>
Co-committed-by: Renovate <renovate@git.end-play.xyz>
2023-04-20 14:40:36 +03:00
11 changed files with 131 additions and 44 deletions

20
.renovaterc Normal file
View File

@@ -0,0 +1,20 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
],
"baseBranches": [
"dev"
],
"packageRules": [
{
"matchUpdateTypes": [
"minor",
"patch",
"pin",
"digest"
],
"automerge": true
}
]
}

View File

@@ -50,12 +50,7 @@ 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. Install optional dependencies [Optional]: 5. Configure "bot" and "owner" with your favorite text editor:
`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
@@ -63,7 +58,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).
7. Configure database and API: 6. 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
@@ -74,15 +69,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.
8. Add bot to the channel: 7. 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.
9. Configure posting time: 8. 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`.
10. Good to go, run it! 9. 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.

View File

@@ -23,6 +23,7 @@
"reports": { "reports": {
"sent": false, "sent": false,
"error": true, "error": true,
"update": true,
"startup": true, "startup": true,
"shutdown": true "shutdown": true
}, },

1
docs/updating.md Normal file
View File

@@ -0,0 +1 @@
# Updating your bot

View File

@@ -59,7 +59,8 @@
"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",

View File

@@ -59,7 +59,8 @@
"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": "✅ Прийняти",

View File

@@ -8,8 +8,7 @@ from traceback import print_exc
from typing import Tuple, Union from typing import Tuple, Union
import aiofiles import aiofiles
from aiohttp import ClientSession, FormData from aiohttp import FormData
from ujson import dumps
from classes.exceptions import ( from classes.exceptions import (
AlbumCreationDuplicateError, AlbumCreationDuplicateError,
@@ -21,10 +20,7 @@ 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:

6
modules/http_client.py Normal file
View File

@@ -0,0 +1,6 @@
from aiohttp import ClientSession
from ujson import dumps
http_session = ClientSession(
json_serialize=dumps,
)

102
poster.py
View File

@@ -1,18 +1,21 @@
from os import getpid, path
from datetime import datetime from datetime import datetime
from os import getpid, path
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, killProc, locale from modules.utils import configGet, jsonLoad, jsonSave, locale
# Import =================================================================================================================================== # Import ===================================================================================================================================
try: try:
from pyrogram.sync import idle
from pyrogram.errors import bad_request_400
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from pyrogram.errors import bad_request_400
from pyrogram.sync import idle
from modules.app import app from modules.app import app
except ModuleNotFoundError: except ModuleNotFoundError:
@@ -22,6 +25,7 @@ except ModuleNotFoundError:
pid = getpid() pid = getpid()
version = 0.1
# Work in progress # Work in progress
# def check_forwards(app): # def check_forwards(app):
@@ -59,9 +63,10 @@ pid = getpid()
# 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 *
@@ -116,10 +121,11 @@ 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)))
app.start() await app.start()
if configGet("startup", "reports"): if configGet("startup", "reports"):
try: try:
@@ -133,7 +139,7 @@ if __name__ == "__main__":
), ),
) )
if downtime.days >= 1: if downtime.days >= 1:
app.send_message( await app.send_message(
configGet("owner"), configGet("owner"),
locale( locale(
"startup_downtime_days", "startup_downtime_days",
@@ -141,7 +147,7 @@ if __name__ == "__main__":
).format(pid, downtime.days), ).format(pid, downtime.days),
) )
elif downtime.hours >= 1: elif downtime.hours >= 1:
app.send_message( await app.send_message(
configGet("owner"), configGet("owner"),
locale( locale(
"startup_downtime_hours", "startup_downtime_hours",
@@ -149,7 +155,7 @@ if __name__ == "__main__":
).format(pid, downtime.hours), ).format(pid, downtime.hours),
) )
else: else:
app.send_message( await app.send_message(
configGet("owner"), configGet("owner"),
locale( locale(
"startup_downtime_minutes", "startup_downtime_minutes",
@@ -158,7 +164,7 @@ if __name__ == "__main__":
).format(pid, downtime.minutes), ).format(pid, downtime.minutes),
) )
else: else:
app.send_message( await app.send_message(
configGet("owner"), configGet("owner"),
locale("startup", "message").format(pid), locale("startup", "message").format(pid),
) )
@@ -167,18 +173,75 @@ if __name__ == "__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()
# if configGet("api_based", "mode"): try:
# 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}"})
idle() if (
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:
app.send_message( await app.send_message(
configGet("owner"), configGet("owner"),
locale("shutdown", "message").format(pid), locale("shutdown", "message").format(pid),
) )
@@ -197,4 +260,7 @@ if __name__ == "__main__":
scheduler.shutdown() scheduler.shutdown()
killProc(pid)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

View File

@@ -1 +0,0 @@
tgcrypto==1.2.5

View File

@@ -1,11 +1,12 @@
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.102 pyrogram==2.0.104
aiofiles~=23.1.0 aiofiles~=23.1.0
tgcrypto==1.2.5
aiohttp~=3.8.4 aiohttp~=3.8.4
psutil~=5.9.4 psutil==5.9.5
pymongo~=4.3.3 pymongo==4.3.3
pillow~=9.4.0 pillow~=9.5.0
ujson~=5.7.0 ujson==5.7.0