25 Commits

Author SHA1 Message Date
Stefano Pigozzi
74c1a85398 Fix README links 2024-05-14 03:13:17 +02:00
Stefano Pigozzi
13dc13e214 Add extra documentation 2024-05-14 03:11:10 +02:00
Stefano Pigozzi
0cd756c82c Ignore .directory files 2024-05-14 03:11:04 +02:00
HYBRID
8f8a188ade Add Hindi language (by @hybridvamp, in #218)
Co-authored-by: Stefano Pigozzi <me@steffo.eu>
2023-10-28 01:53:22 +02:00
dependabot[bot]
e513fa8e95 Bump urllib3 from 1.26.17 to 1.26.18
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.17 to 1.26.18.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.17...1.26.18)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-22 22:30:21 +02:00
dependabot[bot]
1529e26ab4 Bump urllib3 from 1.26.5 to 1.26.17
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.5 to 1.26.17.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.5...1.26.17)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-03 14:21:19 +02:00
dependabot[bot]
d1a8f011cf Bump tornado from 6.3.2 to 6.3.3
Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.3.2 to 6.3.3.
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.3.2...v6.3.3)

---
updated-dependencies:
- dependency-name: tornado
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-15 04:59:17 +02:00
dependabot[bot]
4ad9ef0eab Bump certifi from 2022.12.7 to 2023.7.22
Bumps [certifi](https://github.com/certifi/python-certifi) from 2022.12.7 to 2023.7.22.
- [Commits](https://github.com/certifi/python-certifi/compare/2022.12.07...2023.07.22)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-28 20:17:56 +02:00
dependabot[bot]
8c85f2b819 Bump tornado from 6.1 to 6.3.2 (#203)
Bumps [tornado](https://github.com/tornadoweb/tornado) from 6.1 to 6.3.2.
- [Changelog](https://github.com/tornadoweb/tornado/blob/master/docs/releases.rst)
- [Commits](https://github.com/tornadoweb/tornado/compare/v6.1.0...v6.3.2)

---
updated-dependencies:
- dependency-name: tornado
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 17:43:05 +02:00
dependabot[bot]
e9b64501ff Bump requests from 2.25.1 to 2.31.0 (#202)
Bumps [requests](https://github.com/psf/requests) from 2.25.1 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.25.1...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 03:12:32 +02:00
dependabot[bot]
c553e3d034 Bump certifi from 2020.12.5 to 2022.12.7 (#197)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-22 10:28:44 +01:00
Sergey Krashevich
8bf23d4870 Dockerfile refactoring (#198)
* Dockerfile refactoring
* Update docker-image.yml
* Update CodeQL workflow to match Steffo99/.github
* Add testing workflow using `compileall`
* Use release workflow from Steffo99/.github
* Slightly refactor Dockerfile
* Fix merge tool doing something weird

---------

Co-authored-by: Stefano Pigozzi <me@steffo.eu>
2023-03-22 10:26:21 +01:00
Stefano Pigozzi
b6b3902db5 Improve GitHub Actions workflows (based on #198) 2022-12-19 18:39:19 +01:00
Stefano Pigozzi
2772309239 Remove linux/arm64/v8 too, as something does not work there
:(
2022-12-04 01:42:29 +01:00
Stefano Pigozzi
6007aa451a Remove linux/arm/v7, as pip is broken there? 2022-12-04 01:39:41 +01:00
Stefano Pigozzi
47337d0061 Upgrade docker/build-push-action to v3.2.0 2022-12-04 01:35:14 +01:00
Stefano Pigozzi
3881012f96 Specify linux/arm64/v8 2022-12-04 01:33:45 +01:00
Stefano Pigozzi
85862a0547 Do not tag images with the full name
github does not like it appearently
2022-12-04 01:19:57 +01:00
Stefano Pigozzi
29f3397d00 Add missing commas 2022-12-04 01:18:05 +01:00
Stefano Pigozzi
b6fd15636f Update built image tag names 2022-12-04 01:16:29 +01:00
Stefano Pigozzi
1d1398281a Do not run CodeQL on every push 2022-12-04 01:14:35 +01:00
Stefano Pigozzi
1ed470d492 Update Steffo99/actions-semver to v0.3.5 2022-12-04 01:14:00 +01:00
Stefano Pigozzi
2087b7f446 Build ARM Docker images
Closes #194.
2022-12-04 01:06:49 +01:00
Stefano Pigozzi
fe751cb56d Prevent bypassing the requirement for certain privileges 2022-11-19 17:05:39 +01:00
Stefano Pigozzi
bb99472c84 Add option to disable cash payments (#190)
* Create the `enable_pay_with_cash` and `enable_create_transaction` config options
* Add configuration gates to the `menu_cash` and `menu_edit_credit` buttons
2022-11-19 16:56:49 +01:00
17 changed files with 824 additions and 154 deletions

View File

@@ -1,70 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
queries: security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,44 +0,0 @@
name: "Build Docker image"
on:
release:
types:
- published
defaults:
run:
shell: bash
jobs:
build-docker:
name: "🐳 Build and publish Docker image"
runs-on: ubuntu-latest
steps:
- name: "Checkout repository"
uses: actions/checkout@v2
- name: "❓ Find the release semantic version"
id: semver
uses: Steffo99/actions-semver@v0.1.0
- name: "🔨 Setup Buildx"
uses: docker/setup-buildx-action@v1
- name: "🔑 Login to GitHub Containers"
uses: docker/login-action@v1
with:
registry: ghcr.io
username: RYGhub
password: ${{ secrets.GITHUB_TOKEN }}
- name: "🏗 Build and push the Docker image"
uses: docker/build-push-action@v2
with:
tags: >-
ghcr.io/steffo99/greed:${{ steps.semver.outputs.full }},
ghcr.io/steffo99/greed:${{ steps.semver.outputs.patch }},
ghcr.io/steffo99/greed:${{ steps.semver.outputs.minor }},
ghcr.io/steffo99/greed:${{ steps.semver.outputs.major }},
ghcr.io/steffo99/greed:latest
push: true

15
.github/workflows/quality.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: "Periodic quality and security analysis"
on:
# Every monday at 09:48 UTC
schedule:
- cron: "48 9 * * 1"
workflow_dispatch:
jobs:
codeql:
uses: Steffo99/.github/.github/workflows/quality-python-codeql.yml@main
permissions:
actions: read
contents: read
security-events: write

16
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: "Release new version"
on:
# Creation of a new tag starting with v
push:
tags:
- "v*"
jobs:
test:
uses: ./.github/workflows/test.yml
ghcrio:
uses: Steffo99/.github/.github/workflows/buildrelease-docker.yml@main
needs:
- test

17
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: "Test suite"
on:
# Modification of a project file in the main branch
push:
branches:
- main
# Pull request to the main branch modifying a project file
pull_request:
branches:
- main
# Triggered by a new release
workflow_call:
jobs:
test:
uses: Steffo99/.github/.github/workflows/test-poetry-compileall.yml@main

3
.gitignore vendored
View File

@@ -105,4 +105,5 @@ config/config.ini
config/config.toml
*.sqlite
*.sqlite-journal
data/
data/
.directory

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
.media/screenshot-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
.media/screenshot-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
.media/screenshot-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,20 +1,28 @@
FROM python:3.10 AS labels
LABEL maintainer="Stefano Pigozzi <me@steffo.eu>"
LABEL description="A customizable, multilanguage Telegram shop bot"
FROM python:3.10-alpine AS dependencies
RUN apk add --update build-base python3-dev py-pip musl-dev
FROM labels AS dependencies
COPY requirements.txt ./requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
FROM dependencies AS greed
COPY . /usr/src/greed
WORKDIR /usr/src/greed
COPY ./requirements.txt ./requirements.txt
RUN pip install --no-cache-dir --requirement requirements.txt
#############################################################################
FROM python:3.10-slim AS final
COPY --from=dependencies /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
WORKDIR /usr/src/greed
COPY . /usr/src/greed
FROM greed AS entry
ENTRYPOINT ["python", "-OO"]
CMD ["core.py"]
FROM entry AS environment
ENV PYTHONUNBUFFERED=1
ENV CONFIG_PATH="/etc/greed/config.toml"
ENV DB_ENGINE="sqlite:////var/lib/greed/database.sqlite"
ENV DB_ENGINE="sqlite:////var/lib/greed/database.sqlite"
LABEL org.opencontainers.image.title="greed"
LABEL org.opencontainers.image.description="A customizable, multilanguage Telegram shop bot"
LABEL org.opencontainers.image.licenses="AGPL-3.0-or-later"
LABEL org.opencontainers.image.url="https://github.com/Steffo99/greed/"
LABEL org.opencontainers.image.authors="Stefano Pigozzi <me@steffo.eu>"

View File

@@ -1,11 +1,21 @@
<div align="center">
![](.media/icon-128x128_round.png)
# Greed
A [customizable](/config/template_config.toml), [multilanguage](/strings) Telegram shop bot with [Telegram Payments support](https://core.telegram.org/bots/payments)!
[Customizable](config/template_config.toml) and [multilanguage](strings) Telegram shop bot with [Telegram Payments support](https://core.telegram.org/bots/payments)
\[ [**Documentation**](https://github.com/Steffo99/greed/wiki) | [Support](https://github.com/Steffo99/greed/issues/new/choose) \]
</div>
![](https://i.imgur.com/FdT2tRV.png)
## Links
[![Documentation](https://img.shields.io/badge/docs-available-blue)](docs/README.md)
![](https://i.imgur.com/rDYWdUB.png)
## Screenshots
![](https://i.imgur.com/9plMzO6.png)
![](.media/screenshot-1.png)
![](.media/screenshot-2.png)
![](.media/screenshot-3.png)

View File

@@ -11,8 +11,9 @@
# he - Hebrew, by https://github.com/netanelkoli
# es_mx - Spanish (Mexican), by https://github.com/mastersuv
# pt_br - Brasilian by https://github.com/eufelipemateus
# hi - Hindi by https://github.com/hybridvamp
# The lanugages that messages can be displayed in
enabled_languages = ["it", "en", "uk", "ru", "zh_cn", "he", "es_mx", "pt_br"]
enabled_languages = ["it", "en", "uk", "ru", "zh_cn", "he", "es_mx", "pt_br", "hi"]
# The default language to be set for users whose language cannot be autodetected or whose language is not enabled
default_language = "it"
# The language to fallback to if a string is missing in a specific language
@@ -57,6 +58,15 @@ currency_exp = 2
currency_symbol = "€"
# Cash payment settings
[Payments.Cash]
# Display the "With cash" option in the Add Credit menu
enable_pay_with_cash = true
# Display the "Create transaction" option in the Manager menu
enable_create_transaction = true
# Customize the cash payment text in the strings files!
# Credit card payment settings
[Payments.CreditCard]
# Telegram Payments provider token obtainable at https://t.me/BotFather in the bot's Payments menu

286
docs/README.md Normal file
View File

@@ -0,0 +1,286 @@
# Documentation
> [!WARNING]
>
> First of all, please note that this bot is a **proof-of-concept**!
> No guarantees are provided if you use it, including guarantees of support, so use it in the real world at your own risk!
## History
Greed was developed as an [high school finals project](https://docs.google.com/document/d/1f4MKVr0B7RSQfWTSa_6ZO0LM4nPpky_GX_qdls3EHtQ/edit) and then continued independently of the school thanks to the contributors of various developers, who you see credited on each individual commit.
The bot has since then ceased to be developed, but issues and pull request still are sometimes handled on the creator's free time.
## Features
Greed supports:
- for **users**:
- creating an order
- listing the status of all orders
- adding more funds to the bot's wallet
- via cash
- via Telegram Payments
- changing language
- displaying information and help about the bot
- for **store managers**:
- creating / editing / deleting products
- receiving a live stream of orders to fulfill or refund as messages
- manually adding funds to an user
- displaying the list of performed transactions
- exporting the list of performed transactions as a CSV file
- adding other users as managers and specifying their permissions
## Installation via Docker Engine
This installation procedure assumes you are on a system with `docker` installed, with a supported CPU architecture.
### Requirements
* [Docker Engine](https://docs.docker.com/get-docker/)
* An Internet connection
* A Telegram bot token (obtainable at [@Botfather](https://t.me/Botfather))
* A payment provider token (obtainable by [connecting a provider with your bot](https://t.me/Botfather))
### Steps
1. Run a container using the project's Docker image:
```console
# docker run --volume "$(pwd)/config:/etc/greed" --volume "$(pwd)/strings:/usr/src/greed/strings" --volume "$(pwd)/data:/var/lib/greed" ghcr.io/steffo99/greed
```
1. Edit the configuration file `config.toml` that was created in the `strings` directory, adding your bot and payment tokens to it:
```console
# nano config/config.toml
```
(Press **Ctrl+X** and then two times **Enter** to save and quit `nano`.)
1. _Optional:_ customize the files in the `strings` folder for custom messages.
1. Start the bot:
```console
python -OO core.py
```
1. Open Telegram, and send a `/start` command to your bot to be automatically promoted to 💼 Manager.
1. Stop the bot by pressing **Ctrl+C**.
### Running the bot
After the installation, to run the bot, you'll need to:
1. Run its Docker container from the same directory you installed it from:
```console
# docker run --volume "$(pwd)/config:/etc/greed" --volume "$(pwd)/strings:/usr/src/greed/strings" --volume "$(pwd)/data:/var/lib/greed" ghcr.io/steffo99/greed
```
### Keep the bot running
If you want to keep the bot open even after you closed your terminal window, you'll need to pass the appropriate arguments to the docker command:
1. Set the Docker container to always restart and to detach on successful start:
```console
# docker run --detach --restart always --volume "$(pwd)/config:/etc/greed" --volume "$(pwd)/strings:/usr/src/greed/strings" --volume "$(pwd)/data:/var/lib/greed" ghcr.io/steffo99/greed
```
### Updating
To update the bot, run the following commands:
1. Find the ID of the Docker container of the bot:
```console
# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abcdefabcdef ghcr.io/steffo99/greed "python -OO core.py" 6 seconds ago Up Less than a second relaxed_hypatia
```
1. Stop the Docker container of the bot:
```console
# docker container stop abcdefabcdef
```
1. Remove the Docker container of the bot:
```console
# docker container rm abcdefabcdef
```
1. Pull the latest Docker image of the bot:
```console
# docker pull ghcr.io/steffo99/greed:latest
```
1. Restart the bot with the newly downloaded image:
```console
# docker run --detach --restart always --volume "$(pwd)/config:/etc/greed" --volume "$(pwd)/strings:/usr/src/greed/strings" --volume "$(pwd)/data:/var/lib/greed" ghcr.io/steffo99/greed
```
## Installation via pip
This installation procedure assumes you are on a Linux system, using `bash`, and with `python` installed.
### Requirements
* [Git](https://git-scm.com/)
* [Python 3.8 (or higher)](https://www.python.org/)
* An Internet connection
* A Telegram bot token (obtainable at [@Botfather](https://t.me/Botfather))
* A payment provider token (obtainable by [connecting a provider with your bot](https://t.me/Botfather))
Consider renting a virtual private server (VPS) to host the bot on; a cheap one should do, as greed is pretty lightweight! :)
### Steps
1. Download the project files by running:
```console
$ git clone https://github.com/Steffo99/greed.git
```
1. Enter the newly created folder:
```console
$ cd greed
```
1. Create a new venv:
```console
$ python3 -m venv venv
```
1. Activate the venv:
```console
$ source venv/bin/activate
```
1. Install the project requirements:
```console
$ pip install -r requirements.txt
```
1. _Optional:_ For colored console output, install [coloredlogs](https://pypi.org/project/coloredlogs/):
```console
$ pip install coloredlogs
```
1. Generate the configuration file:
```console
$ python -OO core.py
```
1. Edit the configuration file `config.toml`, adding your bot and payment tokens to it:
```console
$ nano config/config.toml
```
(Press **Ctrl+X** and then two times **Enter** to save and quit `nano`.)
> Beware to not enter your configuration in the `template_config.toml` file, as it will be ignored and may cause trouble when updating.
1. _Optional:_ customize the files in the `strings` folder for custom messages.
1. Start the bot:
```console
$ python -OO core.py
```
1. Open Telegram, and send a `/start` command to your bot to be automatically promoted to 💼 Manager.
1. Stop the bot by pressing **Ctrl+C**.
### Running the bot
After the installation, to run the bot, you'll need to:
1. Activate the venv (if it has not already been activated in the current console session):
```console
$ source venv/bin/activate
```
1. Start the bot:
```bash
$ python -OO core.py
```
### Keep the bot running
If you want to keep the bot open even after you closed your terminal window, you'll need to use an external program, such as:
- `screen` (easier, but doesn't restart automatically)
- `systemd` (recommended, but more complex)
#### `screen`
1. Open a `screen` that will be running the bot with the following command:
```console
$ screen venv/bin/python -OO core.py
```
To safely detach the screen, press Ctrl+A and then Ctrl+D.
#### `systemd`
Assuming you downloaded `greed` in `/srv/greed`:
1. Create a new user named `greed`:
```console
$ useradd greed --system
```
1. Give ownership of the greed folder you downloaded earlier to the `greed` user:
```console
$ chown -R greed: /srv/greed
```
1. Create a new file in `/etc/systemd/system` named `bot-greed.service` with the following contents:
```ini
[Unit]
Name=bot-greed
Description=Greed Bot
Wants=network-online.target
After=network-online.target nss-lookup.target
[Service]
Type=exec
User=greed
WorkingDirectory=/srv/greed
ExecStart=/srv/greed/venv/bin/python -OO /srv/greed/core.py
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
```
1. Start the `bot-greed` service:
```console
$ systemctl start bot-greed
```
1. If everything goes well, enable the bot-greed service, so it will automatically start on a reboot:
```console
$ systemctl enable bot-greed
```
### Updating
To update the bot, run the following commands:
```console
$ git stash
$ git pull
$ git stash pop
```
> If you're using an older version of greed, you may need to recreate the configuration, as greed doesn't use `config.ini` anymore and but uses `config.toml` instead.
## Technical structure
The bot is composed of two parts:
- `core.py`, which handles communication with Telegram and dispatches updates to the workers
- `worker.py`, which handles the conversation flow for a single user, and runs on a separate thread for each conversation
Other resources used by the bot are:
- `utils.py`, containing utility methods
- `nuconfig.py`, containing the configuration loader
- `database.py`, handling interactions with a SQLite or PostgreSQL database
- `localization.py` and `strings/*`, managing the bot's languages
- `config/*`, initially containing the template to generate the configuration file, then also the configuration file itself after the bot has been run once

View File

@@ -1,12 +1,12 @@
# Main requirements
python-telegram-bot==13.5
SQLAlchemy==1.4.14
requests==2.25.1
requests==2.31.0
toml==0.10.2
# Sub-dependencies
APScheduler==3.6.3
certifi==2020.12.5
certifi==2023.7.22
chardet==4.0.0
coloredlogs==15.0
greenlet==1.1.0
@@ -14,6 +14,6 @@ humanfriendly==9.1
idna==2.10
pytz==2021.1
six==1.16.0
tornado==6.1
tornado==6.3.3
tzlocal==2.1
urllib3==1.26.5
urllib3==1.26.18

415
strings/hi.py Normal file
View File

@@ -0,0 +1,415 @@
# Strings / localization file for greed
# Can be edited, but DON'T REMOVE THE REPLACEMENT FIELDS (words surrounded by {curly braces})
# Currency symbol
currency_symbol = ""
# Positioning of the currency symbol
currency_format_string = "{symbol} {value}"
# Quantity of a product in stock
in_stock_format_string = "{quantity} उपलब्ध हैं"
# Copies of a product in cart
in_cart_format_string = "{quantity} कार्ट में"
# Product information
product_format_string = "<b>{name}</b>\n" \
"{description}\n" \
"{price}\n" \
"<b>{cart}</b>"
# Order number, displayed in the order info
order_number = "आदेश #{id}"
# Order info string, shown to the admins
order_format_string = "के द्वारा {user}\n" \
"तिथि पर बनाया गया: {date}\n" \
"\n" \
"{items}\n" \
"कुल: <b>{value}</b>\n" \
"\n" \
"ग्राहक नोट: {notes}\n"
# Order info string, shown to the user
user_order_format_string = "{status_emoji} <b>आदेश {status_text}</b>\n" \
"{items}\n" \
"कुल: <b>{value}</b>\n" \
"\n" \
"टिप्पणियाँ: {notes}\n"
# Transaction page is loading
loading_transactions = "<i>लेन-देन लोड हो रहे हैं...\n" \
"कृपया कुछ सेकंड प्रतीक्षा करें।</i>"
# Transactions page
transactions_page = "पृष्ठ <b>{page}</b>:\n" \
"\n" \
"{transactions}"
# transactions.csv caption
csv_caption = "बॉट डेटाबेस में संचित सभी लेन-देन को समरूपित करने वाला एक 📄 .csv फ़ाइल बनाई गई है।\n" \
"आप इस फ़ाइल को अन्य कार्यक्रमों के साथ खोल सकते हैं, जैसे LibreOffice Calc, डेटा प्रसंस्करण के लिए।"
# Conversation: the start command was sent and the bot should welcome the user
conversation_after_start = "नमस्ते!\n" \
"greed में आपका स्वागत है!\n" \
"यह कोड सॉफ़्टवेयर का 🅱️ <b>बीटा</b> संस्करण है।\n" \
"यह पूरी तरह से उपयोग योग्य है, लेकिन कुछ बग्स अब भी मौजूद हो सकते हैं।\n" \
"यदि आपको कोई मिलता है, तो कृपया उन्हें https://github.com/Steffo99/greed/issues पर रिपोर्ट करें।"
# Conversation: to send an inline keyboard you need to send a message with it
conversation_open_user_menu = "आप क्या करना चाहेंगे?\n" \
"💰 आपके पास <b>{credit}</b> अपने वॉलेट में है।\n" \
"\n" \
"<i>नीचे की कीबोर्ड पर किसी ऑपरेशन का चयन करने के लिए एक कुंजी दबाएं।\n" \
"अगर कीबोर्ड नहीं खुला है, तो आप चार छोटे वर्ग वाले बटन को दबाकर इसे खोल सकते हैं।</i>"
# Conversation: like above, but for administrators
conversation_open_admin_menu = "आप इस दुकान के 💼 <b>प्रबंधक</b> हैं!\n" \
"आप क्या करना चाहेंगे?\n" \
"\n" \
"<i>एक क्रिया चुनने के लिए नीचे कीबोर्ड पर कुंजी दबाएं।\n" \
"अगर कीबोर्ड नहीं खुला है, तो आप मैसेज बार में चार छोटे वर्ग वाले बटन को दबाकर उसे खोल सकते हैं।</i>"
# Conversation: select a payment method
conversation_payment_method = "आप अपने वॉलेट में फंड कैसे जोड़ना चाहेंगे?"
# Conversation: select a product to edit
conversation_admin_select_product = "✏️ आप कौनसा उत्पाद संपादित करना चाहेंगे?"
# Conversation: select a product to delete
conversation_admin_select_product_to_delete = "❌ आप कौनसा उत्पाद हटाना चाहेंगे?"
# Conversation: select a user to edit
conversation_admin_select_user = "संपादित करने के लिए एक उपयोगकर्ता का चयन करें।"
# Conversation: click below to pay for the purchase
conversation_cart_actions = "<i>उपर स्क्रोल करके उन उत्पादों के नीचे जाकर उन्हें कार्ट में जोड़ने के लिए नीचे दिए गए " \
"जोड़ें बटन को दबाएं। जब आपका कार्ट तैयार हो, तो इस संदेश पर वापस जाएं और " \
"नीचे दिए गए डन बटन को दबाएं।</i>"
# Conversation: confirm the cart contents
conversation_confirm_cart = "🛒 आपका कार्ट निम्नलिखित उत्पादों को समेत रखता है:\n" \
"{product_list}" \
"कुल: <b>{total_cost}</b>\n" \
"\n" \
"<i>यदि आप आगे बढ़ना चाहते हैं, तो इस संदेश के नीचे दिए गए डन बटन को दबाएं।\n" \
"रद्द करने के लिए, रद्द बटन दबाएं।</i>"
# Live orders mode: start
conversation_live_orders_start = "आप <b>लाइव आदेश</b> मोड में हैं\n" \
"ग्राहकों द्वारा नई आदेश प्लेस किए जाने पर वे इस चैट में वास्तविक समय में प्रकट होंगे, और आप" \
" उन्हें ✅ पूरा किया गया मार्क" \
" कर सकेंगे या ग्राहक को क्रेडिट ✴️ वापस कर सकेंगे।"
# Live orders mode: stop receiving messages
conversation_live_orders_stop = "<i>फ़ीड बंद करने के लिए इस संदेश के नीचे दिए गए स्टॉप बटन को दबाएं।</i>"
# Conversation: help menu has been opened
conversation_open_help_menu = "आपको किस प्रकार की सहायता चाहिए?"
# Conversation: confirm promotion to admin
conversation_confirm_admin_promotion = "क्या आप इस उपयोगकर्ता को 💼 प्रबंधक बनाना चाहते हैं?\n" \
"यह एक अपरिपरिणामी क्रिया है!"
# Conversation: language select menu header
conversation_language_select = "एक भाषा चुनें:"
# Conversation: switching to user mode
conversation_switch_to_user_mode = "आप 👤 ग्राहक मोड में स्विच कर रहे हैं।\nयदि आप 💼 प्रबंधक मेनू पर वापस जाना चाहते हैं, तो /start के साथ बातचीत फिर से शुरू करें।"
# Notification: the conversation has expired
conversation_expired = "🕐 मैंने कुछ समय से कोई संदेश प्राप्त नहीं किए हैं, इसलिए मैंने संविदान को संचयन संबंधित संसाधनों को बचाने के लिए बंद कर दिया है।\nयदि आप एक नई बातचीत शुरू करना चाहते हैं, तो एक नई /start कमांड भेजें।"
# User menu: order
menu_order = "🛒 उत्पाद आर्डर करें"
# User menu: order status
menu_order_status = "🛍 मेरे आदेश"
# User menu: add credit
menu_add_credit = "💵 फंड जोड़ें"
# User menu: bot info
menu_bot_info = " बॉट जानकारी"
# User menu: cash
menu_cash = "💵 नकद से"
# User menu: credit card
menu_credit_card = "💳 क्रेडिट कार्ड से"
# Admin menu: products
menu_products = "📝 उत्पाद"
# Admin menu: orders
menu_orders = "📦 आदेश"
# Menu: transactions
menu_transactions = "💳 लेन-देन सूची"
# Menu: edit credit
menu_edit_credit = "💰 लेन-देन बनाएं"
# Admin menu: go to user mode
menu_user_mode = "👤 ग्राहक मोड पर स्विच करें"
# Admin menu: add product
menu_add_product = "✨ नया उत्पाद"
# Admin menu: delete product
menu_delete_product = "❌ उत्पाद हटाएं"
# Menu: cancel
menu_cancel = "🔙 रद्द करें"
# Menu: skip
menu_skip = "⏭ छोड़ें"
# Menu: done
menu_done = "✅ किया गया"
# Menu: pay invoice
menu_pay = "💳 भुगतान करें"
# Menu: complete
menu_complete = "✅ पूरा करें"
# Menu: refund
menu_refund = "✴️ वापसी"
# Menu: stop
menu_stop = "🛑 रोकें"
# Menu: add to cart
menu_add_to_cart = " जोड़ें"
# Menu: remove from cart
menu_remove_from_cart = " हटाएं"
# Menu: help menu
menu_help = "❓ मदद / समर्थन"
# Menu: guide
menu_guide = "📖 मार्गदर्शन"
# Menu: next page
menu_next = "▶️ अगला पृष्ठ"
# Menu: previous page
menu_previous = "◀️ पिछला पृष्ठ"
# Menu: contact the shopkeeper
menu_contact_shopkeeper = "👨‍💼 दुकानदार से संपर्क करें"
# Menu: generate transactions .csv file
menu_csv = "📄 लेन-देन .csv फ़ाइल बनाएं"
# Menu: edit admins list
menu_edit_admins = "🏵 प्रबंधक सूची संपादित करें"
# Menu: language
menu_language = "🇬🇧 भाषा"
# Emoji: unprocessed order
emoji_not_processed = "*️⃣ अप्रक्रियित आदेश"
# Emoji: completed order
emoji_completed = "✅ पूरा हुआ आदेश"
# Emoji: refunded order
emoji_refunded = "✴️ वापसी किया गया आदेश"
# Emoji: yes
emoji_yes = "✅ हां"
# Emoji: no
emoji_no = "🚫 नहीं"
# Text: unprocessed order
text_not_processed = "अप्रक्रियित"
# Text: completed order
text_completed = "पूरा हुआ"
# Text: refunded order
text_refunded = "वापसी किया गया"
# Text: product not for sale
text_not_for_sale = "बेचने के लिए नहीं"
# Add product: name?
ask_product_name = "उत्पाद का नाम क्या होना चाहिए?"
# Add product: description?
ask_product_description = "उत्पाद का विवरण क्या होना चाहिए?"
# Add product: price?
ask_product_price = "उत्पाद की मूल्य क्या होनी चाहिए?\n" \
"<code>X</code> दर्ज करें अगर आप इस उत्पाद को अब बेचना नहीं चाहते हैं."
# Add product: image?
ask_product_image = "🖼 आप इस उत्पाद को किस छवि के साथ चाहेंगे?\n" \
"<i>तस्वीर भेजें, या इस चरण को छोड़ें और कोई छवि न जोड़ें.</i>"
# Order product: notes?
ask_order_notes = "क्या आप आदेश के साथ एक नोट छोड़ना चाहेंगे?\n" \
"💼 यह दुकान प्रबंधकों को दिखाई देगा.\n" \
"<i>नोट के साथ एक संदेश भेजें जिसे आप छोड़ना चाहते हैं, या इस संदेश के नीचे स्थित" \
" स्किप बटन दबाकर कुछ न छोड़ें.</i>"
# Refund product: reason?
ask_refund_reason = "इस वापसी के साथ एक कारण जोड़ें।\n" \
"👤 यह ग्राहक को दिखाई देगा।"
# Edit credit: notes?
ask_transaction_notes = "इस लेन-देन के साथ एक नोट जोड़ें।\n" \
"👤 यह ग्राहक को क्रेडिट/डेबिट करने के बाद और लेन-देन लॉग में 💼 प्रबंधकों को दिखाई देगा।"
# Edit credit: amount?
ask_credit = "आप ग्राहक के क्रेडिट को कैसे बदलना चाहते हैं?\n" \
"<i>राशि शामिल करने वाले संदेश को भेजें।\n" \
"ग्राहक के खाते में क्रेडिट जोड़ने के लिए </i><code>+</code><i> और उसे कम करने के लिए </i><code>-</code><i> का प्रयोग करें.</i>"
# Header for the edit admin message
admin_properties = "<b>{name} की अनुमतियाँ:</b>"
# Edit admin: can edit products?
prop_edit_products = "उत्पादों को संपादित करें"
# Edit admin: can receive orders?
prop_receive_orders = "आदेश प्राप्त करें"
# Edit admin: can create transactions?
prop_create_transactions = "लेन-देन प्रबंधित करें"
# Edit admin: show on help message?
prop_display_on_help = "ग्राहक को दिखाएं"
# Thread has started downloading an image and might be unresponsive
downloading_image = "मैं आपकी तस्वीर डाउनलोड कर रहा हूँ!\n" \
"यह कुछ समay लग सकता है... कृपया धैर्य रखें!\n" \
"मैं डाउनलोड करते समay आपके सवालों का उत्तर नहीं देंगा."
# Edit product: current value
edit_current_value = "वर्तमान मूल्य है:\n" \
"<pre>{value}</pre>\n" \
"<i>इस संदेश के नीचे स्थित स्किप बटन दबाकर समान मूल्य रखने के लिए कृपया दबाएं.</i>"
# Payment: cash payment info
payment_cash = "आप दुकान के भौतिक स्थान पर नकद में भुगतान कर सकते हैं।\n" \
"चेकआउट पर भुगतान करें, और मैनेजर को इस आईडी दें:\n" \
"<b>{user_cash_id}</b>"
# Payment: invoice amount
payment_cc_amount = "अपने वॉलेट में कितने फंड जोड़ना चाहेंगे?\n" \
"<i>नीचे दिए गए बटनों के साथ एक राशि का चयन करें, या सामान्य कीबोर्ड के साथ उसे मैन्युअल रूप से दर्ज करें.</i>"
# Payment: add funds invoice title
payment_invoice_title = "फंड जोड़ना"
# Payment: add funds invoice description
payment_invoice_description = "इस चालान को भुगतान करने से {amount} आपके वॉलेट में जोड़ा जाएगा."
# Payment: label of the labeled price on the invoice
payment_invoice_label = "रीलोड"
# Payment: label of the labeled price on the invoice
payment_invoice_fee_label = "लेन-देन शुल्क"
# Notification: order has been placed
notification_order_placed = "एक नया आदेश दिया गया है:\n" \
"{order}"
# Notification: order has been completed
notification_order_completed = "आपका आदेश पूरा हुआ है!\n" \
"{order}"
# Notification: order has been refunded
notification_order_refunded = "आपका आदेश वापस किया गया है!\n" \
"{order}"
# Notification: a manual transaction was applied
notification_transaction_created = " आपके वॉलेट में एक नई लेन-देन लागू की गई है:\n" \
"{transaction}"
# Refund reason
refund_reason = "वापसी का कारण:\n" \
"{reason}"
# Info: informazioni sul bot
bot_info = 'यह बॉट <a href="https://github.com/Steffo99/greed">greed</a> का उपयोग कर रहा है,' \
' जो @Steffo द्वारा बनाया गया है और Telegram भुगतान के लिए जारी किया गया है' \
' <a href="https://github.com/Steffo99/greed/blob/master/LICENSE.txt">' \
'Affero General Public License 3.0</a> के तहत।\n'
# Help: guide
help_msg = "greed का मार्गदर्शन इस पते पर उपलब्ध है:\n" \
"https://github.com/Steffo99/greed/wiki"
# Help: contact shopkeeper
contact_shopkeeper = "वर्तमान में, उपयोगकर्ता सहायता प्रदान करने के लिए उपलब्ध कर्मचारी इस प्रकार हैं:\n" \
"{shopkeepers}\n" \
"<i>किसी नाम पर क्लिक/टैप करें ताकि आप उनसे एक Telegram चैट में संपर्क कर सकें.</i>"
# Success: product has been added/edited to the database
success_product_edited = "✅ उत्पाद को सफलता से जोड़ा/संशोधित किया गया है!"
# Success: product has been added/edited to the database
success_product_deleted = "✅ उत्पाद को सफलता से हटा दिया गया है!"
# Success: order has been created
success_order_created = "✅ आदेश सफलता से भेजा गया!\n" \
"{order}"
# Success: order was marked as completed
success_order_completed = "✅ आपने आदेश #{order_id} को पूरा किया है।"
# Success: order was refunded successfully
success_order_refunded = "✴️ आदेश #{order_id} को वापस किया गया था।"
# Success: transaction was created successfully
success_transaction_created = "✅ लेन-देन को सफलता से बनाया गया था!\n" \
"{transaction}"
# Error: message received not in a private chat
error_nonprivate_chat = "⚠️ यह बॉट केवल निजी चैट में काम करता है।"
# Error: a message was sent in a chat, but no worker exists for that chat.
# Suggest the creation of a new worker with /start
error_no_worker_for_chat = "⚠️ बॉट के साथ बातचीत टूट गई थी।\n" \
"इसे पुनः प्रारंभ करने के लिए, बॉट को /start कमांड भेजें।"
# Error: a message was sent in a chat, but the worker for that chat is not ready.
error_worker_not_ready = "🕒 बॉट के साथ बातचीत अभी प्रारंभ हो रही है।\n" \
"कृपया, और कमांड भेजने से पहले कुछ क्षण प्रतीक्षा करें!"
# Error: add funds amount over max
error_payment_amount_over_max = "⚠️ एक ही लेन-देन में जोड़ने की जा सकने वाली अधिकतम राशि {max_amount} है।"
# Error: add funds amount under min
error_payment_amount_under_min = "⚠️ एक ही लेन-देन में जोड़ने की जा सकने वाली न्यूनतम राशि {min_amount} है।"
# Error: the invoice has expired and can't be paid
error_invoice_expired = "⚠️ इस चालान की समय सीमा समाप्त हो गई है और यह भुगतान नहीं किया जा सकता है। अगर आप फंड जोड़ना चाहते हैं, तो 'फंड जोड़ना' मेनू विकल्प का उपयोग करें।"
# Error: a product with that name already exists
error_duplicate_name = "⚠️ इसी नाम के साथ एक उत्पाद पहले से मौजूद है।"
# Error: not enough credit to order
error_not_enough_credit = "⚠️ आपके पास आदेश देने के लिए पर्याप्त क्रेडिट नहीं है।"
# Error: order has already been cleared
error_order_already_cleared = "⚠️ इस आदेश को पहले से ही प्रक्रिया किया गया है।"
# Error: no orders have been placed, so none can be shown
error_no_orders = "⚠️ आपने अब तक कोई आदेश नहीं दिया है, इसलिए कुछ दिखाने के लिए कुछ नहीं है।"
# Error: selected user does not exist
error_user_does_not_exist = "⚠️ चयनित उपयोगकर्ता मौजूद नहीं है।"
# Fatal: conversation raised an exception
fatal_conversation_exception = "☢️ अरे नहीं! एक <b>त्रुटि</b> ने इस बातचीत को बाधित किया\n" \
"त्रुटि बॉट मालिक को सूचित की गई है ताकि वह इसे ठीक कर सके।\n" \
"बातचीत पुनः प्रारंभ करने के लिए, बॉट को /start कमांड भेजें."

View File

@@ -749,7 +749,8 @@ class Worker(threading.Thread):
keyboard = list()
# Add the supported payment methods to the keyboard
# Cash
keyboard.append([telegram.KeyboardButton(self.loc.get("menu_cash"))])
if self.cfg["Payments"]["Cash"]["enable_pay_with_cash"]:
keyboard.append([telegram.KeyboardButton(self.loc.get("menu_cash"))])
# Telegram Payments
if self.cfg["Payments"]["CreditCard"]["credit_card_token"] != "":
keyboard.append([telegram.KeyboardButton(self.loc.get("menu_credit_card"))])
@@ -763,12 +764,12 @@ class Worker(threading.Thread):
[self.loc.get("menu_cash"), self.loc.get("menu_credit_card"), self.loc.get("menu_cancel")],
cancellable=True)
# If the user has selected the Cash option...
if selection == self.loc.get("menu_cash"):
if selection == self.loc.get("menu_cash") and self.cfg["Payments"]["Cash"]["enable_pay_with_cash"]:
# Go to the pay with cash function
self.bot.send_message(self.chat.id,
self.loc.get("payment_cash", user_cash_id=self.user.identifiable_str()))
# If the user has selected the Credit Card option...
elif selection == self.loc.get("menu_credit_card"):
elif selection == self.loc.get("menu_credit_card") and self.cfg["Payments"]["CreditCard"]["credit_card_token"]:
# Go to the pay with credit card function
self.__add_credit_cc()
# If the user has selected the Cancel option...
@@ -904,7 +905,8 @@ class Worker(threading.Thread):
if self.admin.receive_orders:
keyboard.append([self.loc.get("menu_orders")])
if self.admin.create_transactions:
keyboard.append([self.loc.get("menu_edit_credit")])
if self.cfg["Payments"]["Cash"]["enable_create_transaction"]:
keyboard.append([self.loc.get("menu_edit_credit")])
keyboard.append([self.loc.get("menu_transactions"), self.loc.get("menu_csv")])
if self.admin.is_owner:
keyboard.append([self.loc.get("menu_edit_admins")])
@@ -920,34 +922,34 @@ class Worker(threading.Thread):
self.loc.get("menu_transactions"),
self.loc.get("menu_csv"),
self.loc.get("menu_edit_admins")])
# If the user has selected the Products option...
if selection == self.loc.get("menu_products"):
# If the user has selected the Products option and has the privileges to perform the action...
if selection == self.loc.get("menu_products") and self.admin.edit_products:
# Open the products menu
self.__products_menu()
# If the user has selected the Orders option...
elif selection == self.loc.get("menu_orders"):
# If the user has selected the Orders option and has the privileges to perform the action...
elif selection == self.loc.get("menu_orders") and self.admin.receive_orders:
# Open the orders menu
self.__orders_menu()
# If the user has selected the Transactions option...
elif selection == self.loc.get("menu_edit_credit"):
# If the user has selected the Transactions option and has the privileges to perform the action...
elif selection == self.loc.get("menu_edit_credit") and self.admin.create_transactions:
# Open the edit credit menu
self.__create_transaction()
# If the user has selected the User mode option...
# If the user has selected the User mode option and has the privileges to perform the action...
elif selection == self.loc.get("menu_user_mode"):
# Tell the user how to go back to admin menu
self.bot.send_message(self.chat.id, self.loc.get("conversation_switch_to_user_mode"))
# Start the bot in user mode
self.__user_menu()
# If the user has selected the Add Admin option...
elif selection == self.loc.get("menu_edit_admins"):
# If the user has selected the Add Admin option and has the privileges to perform the action...
elif selection == self.loc.get("menu_edit_admins") and self.admin.is_owner:
# Open the edit admin menu
self.__add_admin()
# If the user has selected the Transactions option...
elif selection == self.loc.get("menu_transactions"):
# If the user has selected the Transactions option and has the privileges to perform the action...
elif selection == self.loc.get("menu_transactions") and self.admin.create_transactions:
# Open the transaction pages
self.__transaction_pages()
# If the user has selected the .csv option...
elif selection == self.loc.get("menu_csv"):
# If the user has selected the .csv option and has the privileges to perform the action...
elif selection == self.loc.get("menu_csv") and self.admin.create_transactions:
# Generate the .csv file
self.__transactions_file()
@@ -1494,6 +1496,10 @@ class Worker(threading.Thread):
lang = "🇧🇷 Português"
keyboard.append([telegram.KeyboardButton(lang)])
options[lang] = "pt_br"
if "hi" in self.cfg["Language"]["enabled_languages"]:
lang = "🇮🇳 हिन्दी"
keyboard.append([telegram.KeyboardButton(lang)])
options[lang] = "hi"
# Send the previously created keyboard to the user (ensuring it can be clicked only 1 time)
self.bot.send_message(self.chat.id,
self.loc.get("conversation_language_select"),