Compare commits
54 Commits
Author | SHA1 | Date |
---|---|---|
bursa-pastoris | ab69ca0aa9 | |
bursa-pastoris | 7720fb1ab7 | |
bursa-pastoris | 38bc5d6afe | |
bursa-pastoris | 84cf9f423e | |
bursa-pastoris | 26e76cde2f | |
bursa-pastoris | b3f4e24743 | |
bursa-pastoris | 042fd00108 | |
bursa-pastoris | 14ba0cbdad | |
bursa-pastoris | 97665ba7c6 | |
bursa-pastoris | 43b1ffd8b0 | |
bursa-pastoris | 979aa86e9f | |
bursa-pastoris | e9538c5c89 | |
bursa-pastoris | 86d8a484c6 | |
bursa-pastoris | a14da6e20f | |
bursa-pastoris | 3711d583b4 | |
bursa-pastoris | 504876307f | |
bursa-pastoris | 8c6bdb9832 | |
bursa-pastoris | bdc29d18db | |
bursa-pastoris | 73daab0c18 | |
bursa-pastoris | 13d921660a | |
bursa-pastoris | b8c44ebe7c | |
bursa-pastoris | 3cf8ca1fb8 | |
bursa-pastoris | 2bef1beef1 | |
bursa-pastoris | 21e0da854c | |
bursa-pastoris | a857520beb | |
bursa-pastoris | 7b015f980b | |
bursa-pastoris | 4a755b2835 | |
bursa-pastoris | 3920645f29 | |
bursa-pastoris | 0cdec513db | |
bursa-pastoris | daf9f5473c | |
bursa-pastoris | 19b4939125 | |
bursa-pastoris | 6793414f57 | |
bursa-pastoris | 23a785b764 | |
bursa-pastoris | 2d5af5087e | |
bursa-pastoris | 0d83497655 | |
bursa-pastoris | b63ca9c67a | |
bursa-pastoris | 47e205f26d | |
bursa-pastoris | ec13527346 | |
bursa-pastoris | feeacbfbe7 | |
bursa-pastoris | 124c0621f6 | |
bursa-pastoris | d79fcf0df4 | |
bursa-pastoris | 1390468567 | |
bursa-pastoris | 3133473fb5 | |
bursa-pastoris | 85577dd8b9 | |
bursa-pastoris | bbc7c08ac0 | |
bursa-pastoris | 0d082b3b77 | |
bursa-pastoris | 14964b4e80 | |
bursa-pastoris | 2f82376db0 | |
bursa-pastoris | 83388cbe68 | |
bursa-pastoris | 7fe01c346f | |
bursa-pastoris | e99e74816e | |
bursa-pastoris | 7db0c761c0 | |
bursa-pastoris | bfc9e793ce | |
bursa-pastoris | a651b66898 |
44
README.md
44
README.md
|
@ -5,13 +5,20 @@ include_toc: true
|
|||
|
||||
Albatrobot is a personal project born as a simple bot to roll dice, but has
|
||||
since then evolved with the addition of more functions, most of which is
|
||||
useless. It thus evolved to the current bloat hodgepodge - but I like it the
|
||||
useless. It thus became to the current bloat hodgepodge - but I like it the
|
||||
same.
|
||||
|
||||
|
||||
## Setup
|
||||
|
||||
To install Albatrobot, follow those steps.
|
||||
Abatrobot is supposed to run in [Debian](https://www.debian.org/), a free
|
||||
operating system. It should work on any other operating system, but it's not
|
||||
tested on any.
|
||||
|
||||
Albatrobot is written in [Python 3](https://www.python.org/), therefore Python
|
||||
is required to use it. Python 3 is part of any standard Debian distribution,
|
||||
but you may have to install it manually in other operating systems (especially
|
||||
in non-GNU/Linux based ones).
|
||||
|
||||
### Installation
|
||||
|
||||
|
@ -22,6 +29,10 @@ To install Albatrobot, follow those steps.
|
|||
source .venv/bin/activate
|
||||
python3 -m pip install -r requirements.txt
|
||||
```
|
||||
3. For `/epiphony` Albatrobot relies on `pyttsx3` library, that requires an
|
||||
external text-to-speech synthesizer. In Debian, this dependence is
|
||||
satisfied by `libespeak1`, that can be installed with `sudo apt install
|
||||
libespeak1`.
|
||||
|
||||
### Configuration
|
||||
|
||||
|
@ -34,22 +45,24 @@ can be tuned to user's needs.
|
|||
server.[^token]
|
||||
- `Users`
|
||||
- `Users`: a comma-separated list of the user IDs of the users allowed to use
|
||||
the bot
|
||||
the bot.
|
||||
- `Admins`: a comma-separated user IDs of the users with admin powers. Admins
|
||||
are always considered Users as well.
|
||||
- `Settings`
|
||||
- `Language`: the language of the bot interface
|
||||
- `MsgCooldown`: the minimum time, in seconds, between two following uses of
|
||||
commands `/Easter` and `/Christmas` by the same user. The time is the same
|
||||
but is considered separately for each command.
|
||||
- `Language`: the language of the bot interface. It must be specified with
|
||||
its 2 letters code. The available languages are the ones listed in
|
||||
[`locales`](./locales).
|
||||
- `ChristmasCooldown`: the minimum time, in seconds, between two consecutive
|
||||
uses of command `/Christmas` by the same user.
|
||||
- `EasterCooldown`: same as above, for `/Easter`.
|
||||
- `Proxy`: proxy settings to connect to Telegram's bot API. The string must
|
||||
follow the syntax
|
||||
`<protocol>://[<username[:<password>]@]<hostname>[:<port>]` (e.g.
|
||||
`socks5://127.0.0.1:9050`)
|
||||
- `YellLang`: language for `/yell` voice messages
|
||||
- `YellSpeed`: speed for `/yell` voice messages
|
||||
`socks5://127.0.0.1:9050`).
|
||||
- `EpiphonyLang`: language for `/Epiphony` voice messages.
|
||||
- `EpiphonySpeed`: speed for `/Epiphony` voice messages.
|
||||
- `Resources`
|
||||
- `CitePath`: path of the document containing the citations for `/Easter`
|
||||
- `CiteArchive`: path of the document containing the citations for `/Easter`
|
||||
command.
|
||||
- `ImgPath`: path of the document containing the images for `Christmas`
|
||||
command.
|
||||
|
@ -68,10 +81,9 @@ opened, then save and close.
|
|||
|
||||
If you run Albatrobot this way - the recommended one - consider the following:
|
||||
|
||||
1. `sleep 10` adds a delay of 10 seconds. It is necessary to allow the system
|
||||
to set the network up and prevents errors due to impossibility to connect to
|
||||
the Internet and to Telegram APIs. You can change the time to comply with
|
||||
your necessities.
|
||||
1. `sleep 10` adds a delay of 10 seconds. It may be necessary to allow the
|
||||
system to set the network up and prevents errors due to impossibility to
|
||||
connect to the Internet and to Telegram APIs.
|
||||
2. If Albatrobot can't be launched, some error information should be saved in
|
||||
`/tmp/albatrobot.txt`.
|
||||
|
||||
|
@ -154,7 +166,7 @@ Check:
|
|||
2. that only one instance of the albatrobot is active for the same Telegram bot
|
||||
user
|
||||
|
||||
**Albatrobot says that there are no avilable citations or images**
|
||||
### Albatrobot says that there are no avilable citations or images
|
||||
|
||||
Check:
|
||||
|
||||
|
|
218
albatrobot.py
218
albatrobot.py
|
@ -1,26 +1,23 @@
|
|||
"""
|
||||
Albatrobot - Telegram bot for RPG groups and similar
|
||||
Copyright (C) 2019, 2020, 2021, 2022 bursa-pastoris
|
||||
|
||||
This file is part of Albatrobot.
|
||||
|
||||
Albatrobot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, version 3 of the License.
|
||||
|
||||
Albatrobot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Albatrobot. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
# Albatrobot - Telegram bot for RPG groups and similar
|
||||
# Copyright (C) 2019, 2020, 2021, 2022, 2023 bursa-pastoris
|
||||
#
|
||||
# This file is part of Albatrobot.
|
||||
#
|
||||
# Albatrobot is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Albatrobot is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with Albatrobot. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import csv
|
||||
from datetime import datetime
|
||||
import glob
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
|
@ -34,15 +31,14 @@ import Levenshtein
|
|||
import psutil
|
||||
from rolldice import roll_dice, rolldice
|
||||
from telegram import BotCommand
|
||||
from telegram.constants import ChatAction, ChatType, ParseMode
|
||||
from telegram.constants import ChatAction, ChatMemberStatus, ChatType, ParseMode
|
||||
|
||||
from constants import *
|
||||
|
||||
# Prepare paths
|
||||
required_paths = ['log',TMPVOICEDIR]
|
||||
required_paths = [LOGDIR,TMPVOICEDIR]
|
||||
for i in required_paths:
|
||||
if not os.path.exists(i):
|
||||
os.mkdir(i)
|
||||
os.makedirs(i,exist_ok=True)
|
||||
|
||||
# Logging
|
||||
logger = logging.getLogger('albatrobot_logger')
|
||||
|
@ -51,7 +47,7 @@ logformat = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
|
|||
loghandler_toconsole = logging.StreamHandler()
|
||||
loghandler_toconsole.setLevel(logging.DEBUG)
|
||||
loghandler_toconsole.setFormatter(logformat)
|
||||
loghandler_tofile = logging.FileHandler('log/albatrobot.log')
|
||||
loghandler_tofile = logging.FileHandler(f'{LOGDIR}/albatrobot.log')
|
||||
loghandler_tofile.setLevel(logging.DEBUG)
|
||||
loghandler_tofile.setFormatter(logformat)
|
||||
logger.addHandler(loghandler_toconsole)
|
||||
|
@ -62,7 +58,7 @@ logger.addHandler(loghandler_tofile)
|
|||
def closest(good_list, item):
|
||||
"""Return the item(s) of good_list closest to item.
|
||||
|
||||
"Closest" means "with the shortest Levenshtein distance.
|
||||
"Closest" means "with the shortest Levenshtein distance".
|
||||
"""
|
||||
distances = {}
|
||||
for i in good_list:
|
||||
|
@ -97,7 +93,7 @@ async def unknown_command(update, context):
|
|||
|
||||
# Basic functions
|
||||
async def start(update, context):
|
||||
"""Show a message when a user contacts the bot for the first time."""
|
||||
"""Show basic info when a user contacts the bot for the first time."""
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
text=_("Hello, I'm Albatrobot\! Type \/help for help\!\n"
|
||||
|
@ -128,17 +124,17 @@ async def help(update, context):
|
|||
"""Show a help message.
|
||||
|
||||
The message doesn't correspond to the inline suggestion set in
|
||||
@BotFather, that must be set manually through a Telegram client.
|
||||
@BotFather. They can be set issuing the command /init.
|
||||
"""
|
||||
# Common commands
|
||||
ccom_header = _('*Albatrobot commands*')
|
||||
ccom_help = {
|
||||
com_header = _('*Albatrobot commands*')
|
||||
com_help = {
|
||||
_('christmas'):_('get an image'),
|
||||
_('easter')+_(' `\(\<author\>\)`'):_('get a citation from given author,'
|
||||
' or a random one if no author is specified\.'),
|
||||
_('end\_of\_year\_dinner'):_('send all citations in the archive to a'
|
||||
' random user\.'),
|
||||
_('epiphony')+_(' `\(\<text\>\)`'):_('get a voice message from'
|
||||
_('epiphony')+_(' `<text\>`'):_('get a voice message from'
|
||||
' Albatrobot reading given text'),
|
||||
_('help'):_('get help about bot commands\.'),
|
||||
_('legal'):_('get legal info about privacy and copyright\.'),
|
||||
|
@ -147,53 +143,52 @@ async def help(update, context):
|
|||
' modifiers\.'),
|
||||
_('version'):_("get Albatrobot's version")
|
||||
}
|
||||
ccom_help = [f'\- \/{i}: {ccom_help[i]}'
|
||||
for i in ccom_help]
|
||||
ccom_help.sort()
|
||||
ccom_help = '\n'.join(ccom_help)
|
||||
ccom_help = f'{ccom_header}\n{ccom_help}'
|
||||
com_help = [f'\- \/{i}: {com_help[i]}' for i in com_help]
|
||||
com_help.sort()
|
||||
com_help = '\n'.join(com_help)
|
||||
com_help = f'{com_header}\n{com_help}'
|
||||
|
||||
# Admin commands
|
||||
acom_header = _('*Additional commands for bot admins*')
|
||||
acom_help = {
|
||||
_('init'):_('reinitialize the bot\. This updates inline suggestions'
|
||||
adm_header = _('*Additional commands for bot admins*')
|
||||
adm_help = {
|
||||
_('reset'):_('reset the bot\. This updates inline suggestions'
|
||||
' and purges /epiphony cached files\.'),
|
||||
_('stop'):_('stop Albatrobot\. To be used _only_ in case of emergency:'
|
||||
' restarting the bot after this command is used requires direct'
|
||||
' access to the server\.')
|
||||
}
|
||||
acom_help = [f'\- \/{i}: {acom_help[i]}'
|
||||
for i in acom_help]
|
||||
acom_help.sort()
|
||||
acom_help = '\n'.join(acom_help)
|
||||
acom_help = f'{acom_header}\n{acom_help}'
|
||||
adm_help = [f'\- \/{i}: {adm_help[i]}' for i in adm_help]
|
||||
adm_help.sort()
|
||||
adm_help = '\n'.join(adm_help)
|
||||
adm_help = f'{adm_header}\n{adm_help}'
|
||||
|
||||
# Addendum
|
||||
non_admin_addendum = _(
|
||||
nonadm_addendum = _(
|
||||
'Bot admins have access to additional commands and can get help on'
|
||||
' them using /help in a private chat\.'
|
||||
)
|
||||
|
||||
# Actually sending stuff
|
||||
# Actually send stuff
|
||||
if (update.effective_chat.type == ChatType.PRIVATE
|
||||
and update.effective_user.id in ADMINS):
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_user.id,
|
||||
text=_(f'{ccom_help}\n\n{acom_help}'),
|
||||
parse_mode=ParseMode.MARKDOWN_V2
|
||||
)
|
||||
help_text = _(f'{com_help}\n\n{adm_help}')
|
||||
else:
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
text=_(f'{ccom_help}\n\n{non_admin_addendum}'),
|
||||
parse_mode=ParseMode.MARKDOWN_V2
|
||||
)
|
||||
help_text = _(f'{com_help}\n\n{nonadm_addendum}')
|
||||
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
text=help_text,
|
||||
parse_mode=ParseMode.MARKDOWN_V2
|
||||
)
|
||||
|
||||
|
||||
async def init(update, context):
|
||||
"""Initialize the bot."""
|
||||
async def reset(update, context):
|
||||
"""Reset the bot."""
|
||||
# Set commands suggestions
|
||||
commands=[BotCommand(_('roll'),_('Roll dice'))]
|
||||
commands=[BotCommand(_('christmas'),_('Get an image')),
|
||||
BotCommand(_('easter'),_('Get a citation')),
|
||||
BotCommand(_('end_of_year_dinner'),_('Send all citations to a random user')),
|
||||
BotCommand(_('help'),_('Get help'))]
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
text=_('Initializing...'))
|
||||
|
@ -208,17 +203,25 @@ async def init(update, context):
|
|||
|
||||
async def legal(update, context):
|
||||
"""
|
||||
Send legal information (privacy and copyright).
|
||||
Send legal information about privacy and copyright.
|
||||
"""
|
||||
logger.info('A user asked for legal info.')
|
||||
if LANG != "en":
|
||||
note=_('The only official version is the English one and any'
|
||||
' imperfect translation would be misleading. Therefore, this'
|
||||
' document will not be translated.')
|
||||
else:
|
||||
note=""
|
||||
await context.bot.send_chat_action(
|
||||
chat_id=update.effective_chat.id,
|
||||
action=ChatAction.UPLOAD_DOCUMENT)
|
||||
with open('doc/LEGAL.md','rb') as legalnotes:
|
||||
with open('doc/LEGAL.pdf','rb') as legalnotes:
|
||||
await context.bot.send_document(
|
||||
chat_id=update.effective_chat.id,
|
||||
document=legalnotes,
|
||||
filename='albatrobot-legal-notes.txt')
|
||||
logger.info('A user asked for legal info.')
|
||||
filename='albatrobot-legal-notes.pdf',
|
||||
caption=note
|
||||
)
|
||||
|
||||
|
||||
async def version(update, context):
|
||||
|
@ -232,22 +235,23 @@ async def version(update, context):
|
|||
|
||||
# Commands
|
||||
async def christmas(update, context):
|
||||
"""Send a (hopefully funny) image from the archive."""
|
||||
imgs = glob.glob(str(IMGPATH+'/*'))
|
||||
try:
|
||||
last_msg = context.user_data['last_christmas']
|
||||
if datetime.now()-last_msg < MSGCOOLDOWN:
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_user.id,
|
||||
text=_("Christmas is good, but you can't invoke it so often! "
|
||||
"Try again in some seconds...")
|
||||
)
|
||||
logger.info('A user wants too much Christmas.')
|
||||
return
|
||||
# If last_christmas doesn't exist, it just means the user never used
|
||||
# /christmas since last bot start.
|
||||
except KeyError:
|
||||
pass
|
||||
"""Send a random image from the archive."""
|
||||
last_msg = context.user_data.get('last_christmas',
|
||||
datetime.fromisoformat('1970-01-01T00:00'))
|
||||
if datetime.now()-last_msg < CHRISTMASCOOLDOWN:
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
text=_("Christmas is good, but you can't invoke it so often! "
|
||||
"Try again in some seconds...")
|
||||
)
|
||||
logger.info('A user wants too much Christmas.')
|
||||
return
|
||||
|
||||
with open(f'{IMGPATH}/imgs.csv','r') as imgs_file:
|
||||
imgs = list(csv.DictReader(imgs_file))
|
||||
img = random.choice(imgs)
|
||||
img_file = img['filename']
|
||||
img_capt = img['caption']
|
||||
|
||||
await context.bot.send_chat_action(
|
||||
chat_id=update.effective_chat.id,
|
||||
|
@ -255,7 +259,8 @@ async def christmas(update, context):
|
|||
)
|
||||
await context.bot.send_photo(
|
||||
chat_id=update.effective_chat.id,
|
||||
photo=open(random.choice(imgs), 'rb')
|
||||
photo=open(f'{IMGPATH}/{img_file}', 'rb'),
|
||||
caption=img_capt
|
||||
)
|
||||
context.user_data['last_christmas'] = datetime.now()
|
||||
|
||||
|
@ -263,22 +268,18 @@ async def christmas(update, context):
|
|||
async def easter(update, context):
|
||||
"""Send a citation from the archive.
|
||||
|
||||
User can either choose the source or let the bot pick a random one.
|
||||
User can either choose the author or let the bot pick a random one.
|
||||
"""
|
||||
try:
|
||||
last_msg = context.user_data['last_easter']
|
||||
if datetime.now()-last_msg < MSGCOOLDOWN:
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_user.id,
|
||||
text=_("Easter is good, but you can't invoke it so often!"
|
||||
" Retry in some seconds...")
|
||||
)
|
||||
logger.info('A user wants too much Easter.')
|
||||
return
|
||||
# If last_easter doesn't exist, it just means the user never used /easter
|
||||
# since last bot start.
|
||||
except KeyError:
|
||||
pass
|
||||
last_msg = context.user_data.get('last_easter',
|
||||
datetime.fromisoformat('1970-01-01T00:00'))
|
||||
if datetime.now()-last_msg < EASTERCOOLDOWN:
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
text=_("Easter is good, but you can't invoke it so often!"
|
||||
" Retry in some seconds...")
|
||||
)
|
||||
logger.info('A user wants too much Easter.')
|
||||
return
|
||||
|
||||
with open(CITARCHIVE,'r') as cits_file:
|
||||
cits = csv.DictReader(cits_file)
|
||||
|
@ -331,8 +332,6 @@ async def easter(update, context):
|
|||
|
||||
async def end_of_year_dinner(update, context):
|
||||
"""Send a user each citation from the archive."""
|
||||
# Importing here is so that the citations list can be updated without
|
||||
# restarting the bot.
|
||||
with open(CITARCHIVE,'r') as cits_file:
|
||||
cits_archive = list(csv.DictReader(cits_file))
|
||||
cits_number = 0
|
||||
|
@ -366,12 +365,15 @@ async def end_of_year_dinner(update, context):
|
|||
|
||||
async def epiphony(update, context):
|
||||
sentence = ' '.join(context.args).upper()
|
||||
# Handle command without args
|
||||
if len(sentence) == 0:
|
||||
await context.bot.send_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
text=_('What should I say?')
|
||||
)
|
||||
# Handle command with args
|
||||
else:
|
||||
# Generate and send audio
|
||||
sentence_hash = hashlib.md5(sentence.encode(encoding='UTF-8')).hexdigest()
|
||||
voice_file = f'{TMPVOICEDIR}/{sentence_hash}.ogg'
|
||||
await context.bot.send_chat_action(
|
||||
|
@ -379,15 +381,31 @@ async def epiphony(update, context):
|
|||
action=ChatAction.RECORD_VOICE)
|
||||
if not os.path.exists(voice_file):
|
||||
engine = pyttsx3.init()
|
||||
engine.setProperty('voice',YELLLANG)
|
||||
engine.setProperty('rate',YELLSPEED)
|
||||
engine.setProperty('voice',EPIPHONYLANG)
|
||||
engine.setProperty('rate',EPIPHONYSPEED)
|
||||
engine.save_to_file(sentence,voice_file)
|
||||
engine.runAndWait()
|
||||
time.sleep(1) # Workaround to prevent ReferenceError due to using
|
||||
# pyttsx3 with threads
|
||||
# pyttsx3 with asyncio
|
||||
await context.bot.send_voice(
|
||||
chat_id=update.effective_chat.id,
|
||||
voice=open(voice_file,'rb'))
|
||||
voice=open(voice_file,'rb'),
|
||||
reply_to_message_id=update.effective_message.reply_to_message.message_id
|
||||
if update.effective_message.reply_to_message else None,
|
||||
caption=_('Voice message from {sender_name}.'.format(
|
||||
sender_name=update.effective_user.first_name))
|
||||
)
|
||||
# If in group chat and have permission, delete the message that issued
|
||||
# the command
|
||||
bot_data = await context.bot.get_me()
|
||||
bot_chatmember = await context.bot.get_chat_member(
|
||||
chat_id=update.effective_chat.id,
|
||||
user_id=bot_data.id)
|
||||
if (bot_chatmember.status == ChatMemberStatus.ADMINISTRATOR
|
||||
and bot_chatmember.can_delete_messages):
|
||||
await context.bot.delete_message(
|
||||
chat_id=update.effective_chat.id,
|
||||
message_id=update.effective_message.message_id)
|
||||
|
||||
|
||||
async def roll(update, context):
|
||||
|
|
12
constants.py
12
constants.py
|
@ -12,11 +12,12 @@ ADMINS = [int(admin) for admin in config["Users"]["Admins"].split(",")]
|
|||
USERS = [int(user) for user in config["Users"]["Users"].split(",")]
|
||||
|
||||
# Settings
|
||||
LANG = config["Settings"]["Language"]
|
||||
MSGCOOLDOWN = timedelta(seconds=int(config["Settings"]["MsgCooldown"]))
|
||||
LANG = config["Settings"]["Language"] if len(config["Settings"]["Language"]) > 0 else "en"
|
||||
CHRISTMASCOOLDOWN = timedelta(seconds=int(config["Settings"]["ChristmasCooldown"]))
|
||||
EASTERCOOLDOWN = timedelta(seconds=int(config["Settings"]["EasterCooldown"]))
|
||||
PROXY = config["Settings"]["Proxy"]
|
||||
YELLLANG = config['Settings']['YellLang']
|
||||
YELLSPEED = config['Settings']['YellSpeed']
|
||||
EPIPHONYLANG = config['Settings']['EpiphonyLang']
|
||||
EPIPHONYSPEED = config['Settings']['EpiphonySpeed']
|
||||
|
||||
# Resources
|
||||
CITARCHIVE = config["Resources"]["CitArchive"]
|
||||
|
@ -24,4 +25,5 @@ IMGPATH = config["Resources"]["ImgPath"]
|
|||
|
||||
# Private
|
||||
TMPVOICEDIR = 'tmp'
|
||||
VERSION = "0.3"
|
||||
LOGDIR = 'log'
|
||||
VERSION = '0.4.0'
|
||||
|
|
|
@ -3,6 +3,44 @@ gitea: none
|
|||
include_toc: true
|
||||
---
|
||||
|
||||
## v0.4.0
|
||||
### Misc
|
||||
|
||||
- Fix `VERSION` in `constants.py` to allow Telegram markup
|
||||
- Fix Italian translation
|
||||
|
||||
## v0.4.0-alpha
|
||||
### Features
|
||||
|
||||
- In groups, `/Epiphony` now:
|
||||
- deletes the message issuing the command,
|
||||
- sends the voice message as an answer to the same message to wich the
|
||||
command was issued as a reply to (if any)
|
||||
- Add support for captions to `/Christmas` images
|
||||
- `/Christmas` and `/Easter` cooldown times are now independent from each other
|
||||
|
||||
### Misc
|
||||
|
||||
- If no language is set, default to English
|
||||
- `/legal` now sends the information in PDF (instead of TXT)
|
||||
- If the instance is in a language other than English, `/legal` now explains
|
||||
that and why the legal info will not be translated
|
||||
- Fix privacy info (without privacy implications: simply, `/legal` was added to
|
||||
the list of commands that generate anonymous logs)
|
||||
- Fix Italian translation
|
||||
- Fix and improve documentation
|
||||
- Code cleanup
|
||||
- Minor fixes and enhancements
|
||||
|
||||
|
||||
## V0.3.1
|
||||
|
||||
### Misc
|
||||
|
||||
- Update copyright headers
|
||||
- Add inline suggestions for all common commands that don't require arguments
|
||||
- Add stuff to v0.3 changelog
|
||||
|
||||
## v0.3
|
||||
### New features
|
||||
|
||||
|
@ -16,8 +54,13 @@ include_toc: true
|
|||
### Enhancements
|
||||
|
||||
- Better help texts
|
||||
- Citations for /easter are now stored in a CSV file
|
||||
- Enhance "no images available" image
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Close #4, #5 and #6
|
||||
|
||||
### Code
|
||||
|
||||
- Constants moved to own module
|
||||
|
|
|
@ -10,7 +10,7 @@ Everyone is welcome to propose his contribution:
|
|||
But note that, as Albatrobot is a personal project, I will merge only the
|
||||
contributions that I find useful or interesting *for me*. However, everyone
|
||||
can enjoy the rights granted by [AGPL-3.0-only license](./LICENSE) to fork the
|
||||
project and do whatever they want on their copies (as long as the license is
|
||||
project and do whatever he want on their copies (as long as the license is
|
||||
honoured).
|
||||
|
||||
|
||||
|
|
|
@ -20,10 +20,11 @@ Note however that:
|
|||
Also, anonymous logs are stored:
|
||||
|
||||
* when a user uses one of the following commands:
|
||||
* `/source`
|
||||
* `/end_of_year_dinner`
|
||||
* `/christmas`, if the user hits the time limit
|
||||
* `/easter`, if the user hits the time limit or asks for an unknown author
|
||||
* `/end_of_year_dinner`
|
||||
* `/legal`
|
||||
* `/source`
|
||||
* whenever an error is raised
|
||||
|
||||
The logs are intended for debug and issue resolution only and *never* contain
|
||||
|
|
Binary file not shown.
|
@ -16,6 +16,7 @@ To release a new version:
|
|||
- [ ] in `constants.py`
|
||||
- [ ] in the updated translations
|
||||
- [ ] Update documentation not listed below
|
||||
- [ ] Update `doc/LEGAL.pdf`
|
||||
- [ ] Update `doc/README.md`
|
||||
- [ ] Update `doc/CHANGELOG.md`
|
||||
- [ ] _At least now_, test _each command_, both as admin and simple user, to
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
# This file is distributed under the same license as the Albatrobot package.
|
||||
# bursa-pastoris <bursapastoris at disroot dot org>, 2021, 2023.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Albatrobot 0.3\n"
|
||||
"Project-Id-Version: Albatrobot 0.4.0-alpha\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-23 00:00+0000\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:00+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,55 +16,55 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: main.py:48 main.py:60 albatrobot.py:161
|
||||
#: main.py:46 main.py:58 albatrobot.py:156
|
||||
msgid "stop"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:48 main.py:69 albatrobot.py:159
|
||||
#: main.py:46 main.py:67 albatrobot.py:154
|
||||
msgid "init"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:65 albatrobot.py:143
|
||||
#: main.py:63 albatrobot.py:139 albatrobot.py:191
|
||||
msgid "help"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:73 albatrobot.py:144
|
||||
#: main.py:71 albatrobot.py:140
|
||||
msgid "legal"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:77 albatrobot.py:148
|
||||
#: main.py:75 albatrobot.py:144
|
||||
msgid "version"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:84 albatrobot.py:136
|
||||
#: main.py:82 albatrobot.py:132 albatrobot.py:188
|
||||
msgid "christmas"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:88 albatrobot.py:137
|
||||
#: main.py:86 albatrobot.py:133 albatrobot.py:189
|
||||
msgid "easter"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:92
|
||||
#: main.py:90 albatrobot.py:190
|
||||
msgid "end_of_year_dinner"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:96 albatrobot.py:141
|
||||
#: main.py:94 albatrobot.py:137
|
||||
msgid "epiphony"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:100 albatrobot.py:145 albatrobot.py:196
|
||||
#: main.py:98 albatrobot.py:141
|
||||
msgid "roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:81
|
||||
#: albatrobot.py:77
|
||||
msgid "User not authorized."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:89
|
||||
#: albatrobot.py:85
|
||||
msgid "Unknown command."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:103
|
||||
#: albatrobot.py:99
|
||||
msgid ""
|
||||
"Hello, I'm Albatrobot\\! Type \\/help for help\\!\n"
|
||||
"\n"
|
||||
|
@ -76,140 +75,158 @@ msgid ""
|
|||
"albatrobot)\\._"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:121
|
||||
#: albatrobot.py:117
|
||||
msgid "Albatrobot will be stopped in a few moments."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:134
|
||||
#: albatrobot.py:130
|
||||
msgid "*Albatrobot commands*"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:136
|
||||
#: albatrobot.py:132
|
||||
msgid "get an image"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:137
|
||||
#: albatrobot.py:133
|
||||
msgid " `\\(\\<author\\>\\)`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:137
|
||||
#: albatrobot.py:133
|
||||
msgid ""
|
||||
"get a citation from given author, or a random one if no author is "
|
||||
"specified\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:139
|
||||
#: albatrobot.py:135
|
||||
msgid "end\\_of\\_year\\_dinner"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:139
|
||||
#: albatrobot.py:135
|
||||
msgid "send all citations in the archive to a random user\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:141
|
||||
msgid " `\\(\\<text\\>\\)`"
|
||||
#: albatrobot.py:137
|
||||
msgid " `<text\\>`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:141
|
||||
#: albatrobot.py:137
|
||||
msgid "get a voice message from Albatrobot reading given text"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:143
|
||||
#: albatrobot.py:139
|
||||
msgid "get help about bot commands\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:144
|
||||
#: albatrobot.py:140
|
||||
msgid "get legal info about privacy and copyright\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:145
|
||||
#: albatrobot.py:141
|
||||
msgid " `\\<dice\\>\\(\\<modifiers\\>\\)`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:145
|
||||
#: albatrobot.py:141
|
||||
msgid ""
|
||||
"roll dice, with or without modifiers\\. Launch without arguments to get help "
|
||||
"on the modifiers\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:148
|
||||
#: albatrobot.py:144
|
||||
msgid "get Albatrobot's version"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:157
|
||||
#: albatrobot.py:152
|
||||
msgid "*Additional commands for bot admins*"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:159
|
||||
#: albatrobot.py:154
|
||||
msgid ""
|
||||
"reinitialize the bot\\. This updates inline suggestions and purges /epiphony "
|
||||
"cached files\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:161
|
||||
#: albatrobot.py:156
|
||||
msgid ""
|
||||
"stop Albatrobot\\. To be used _only_ in case of emergency: restarting the "
|
||||
"bot after this command is used requires direct access to the server\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:173
|
||||
#: albatrobot.py:167
|
||||
msgid ""
|
||||
"Bot admins have access to additional commands and can get help on them "
|
||||
"using /help in a private chat\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:182
|
||||
#: albatrobot.py:174
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{ccom_help}\n"
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{acom_help}"
|
||||
"{adm_help}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:176
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{nonadm_addendum}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:188
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{ccom_help}\n"
|
||||
"\n"
|
||||
"{non_admin_addendum}"
|
||||
msgid "Get an image"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:196
|
||||
msgid "Roll dice"
|
||||
#: albatrobot.py:189
|
||||
msgid "Get a citation"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:199
|
||||
#: albatrobot.py:190
|
||||
msgid "Send all citations to a random user"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:191
|
||||
msgid "Get help"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:194
|
||||
msgid "Initializing..."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:203
|
||||
#: albatrobot.py:198
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:228
|
||||
#: albatrobot.py:217
|
||||
msgid ""
|
||||
"The only official version is the English one and any imperfect translation "
|
||||
"would be misleading. Therefore, this document will not be translated."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:227
|
||||
msgid "*Albatrobot's version:* {}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:242
|
||||
#: albatrobot.py:240
|
||||
msgid ""
|
||||
"Christmas is good, but you can't invoke it so often! Try again in some "
|
||||
"seconds..."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:273
|
||||
#: albatrobot.py:274
|
||||
msgid ""
|
||||
"Easter is good, but you can't invoke it so often! Retry in some seconds..."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:296
|
||||
#: albatrobot.py:293
|
||||
msgid "The most similar is {}."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:300
|
||||
#: albatrobot.py:297
|
||||
msgid "The most similar are {} and {}."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:304
|
||||
#: albatrobot.py:301
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Author {required_author} is not present in the archive! {suggestion}\n"
|
||||
|
@ -217,7 +234,7 @@ msgid ""
|
|||
"N.b.: CaSe Is ImPoRtAnT!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:324 albatrobot.py:352
|
||||
#: albatrobot.py:321 albatrobot.py:347
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{cit}\n"
|
||||
|
@ -225,142 +242,147 @@ msgid ""
|
|||
"~{author}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:345
|
||||
#: albatrobot.py:340
|
||||
msgid "Hello there, here an end of year dinner offered by {}!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:359
|
||||
#: albatrobot.py:354
|
||||
#, python-brace-format
|
||||
msgid "End of year dinner of {cits_number} plates delvered to {dest}!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:372
|
||||
#: albatrobot.py:368
|
||||
msgid "What should I say?"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:402
|
||||
msgid "add `n` to the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:403
|
||||
msgid "subtract `n` from the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:404
|
||||
msgid "multiply the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:405
|
||||
msgid "divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:406
|
||||
msgid "floor divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:407
|
||||
msgid "exponentiate the roll to `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:408
|
||||
msgid "keep highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:409
|
||||
msgid "keep lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:410
|
||||
msgid "drop highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:411
|
||||
msgid "drop lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:412
|
||||
msgid "explode rolls equal to `n` \\(defaults to die size\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:413
|
||||
msgid "explode rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:414
|
||||
msgid "explode rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:415
|
||||
msgid "count failures as rolls lower than `n`"
|
||||
#: albatrobot.py:391
|
||||
#, python-brace-format
|
||||
msgid "Voice message from {sender_name}."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:416
|
||||
msgid "count failures as rolls higher than `n`"
|
||||
msgid "add `n` to the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:417
|
||||
msgid "count successes as rolls lower than `n`"
|
||||
msgid "subtract `n` from the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:418
|
||||
msgid "count successes as rolls higher than `n`"
|
||||
msgid "multiply the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:419
|
||||
msgid "penetrate rolls equal to dice size"
|
||||
msgid "divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:420
|
||||
msgid "penetrate rolls lower than `n`"
|
||||
msgid "floor divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:421
|
||||
msgid "penetrate rolls higher than `n`"
|
||||
msgid "exponentiate the roll to `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:422
|
||||
msgid "add `n` to each roll"
|
||||
msgid "keep highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:423
|
||||
msgid "subtract `n` from each roll"
|
||||
msgid "keep lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:424
|
||||
msgid "multiply by `n` each roll"
|
||||
msgid "drop highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:425
|
||||
msgid "drop lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:426
|
||||
msgid "explode rolls equal to `n` \\(defaults to die size\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:427
|
||||
msgid "explode rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:428
|
||||
msgid "explode rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:429
|
||||
msgid "count failures as rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:430
|
||||
msgid "count failures as rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:431
|
||||
msgid "count successes as rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:432
|
||||
msgid "count successes as rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:433
|
||||
msgid "penetrate rolls equal to dice size"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:434
|
||||
msgid "penetrate rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:435
|
||||
msgid "penetrate rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:436
|
||||
msgid "add `n` to each roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:437
|
||||
msgid "subtract `n` from each roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:438
|
||||
msgid "multiply by `n` each roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:439
|
||||
msgid ""
|
||||
"reroll each dice that rolled `n` until there are no `n` left\\(defaults to "
|
||||
"`1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:427
|
||||
#: albatrobot.py:441
|
||||
msgid "reroll once each dice that rolled `n` \\(defaults to 1\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:429
|
||||
#: albatrobot.py:443
|
||||
msgid ""
|
||||
"reroll dice that rolled lower than `n` until there are no results lower than "
|
||||
"`n` left"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:431
|
||||
#: albatrobot.py:445
|
||||
msgid ""
|
||||
"reroll dice that rolled higher than `n` until there no results higher than "
|
||||
"`n` left"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:433
|
||||
#: albatrobot.py:447
|
||||
msgid "reroll once dice that roll lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:434
|
||||
#: albatrobot.py:448
|
||||
msgid "reroll once dice that roll higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:439
|
||||
#: albatrobot.py:453
|
||||
msgid ""
|
||||
"To roll, use the syntax `\\<number of dice\\>d\\<dice size\\>`\\. You can "
|
||||
"also use the following modifiers\\. Note that:\n"
|
||||
|
@ -372,15 +394,15 @@ msgid ""
|
|||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:458
|
||||
#: albatrobot.py:472
|
||||
msgid "You can roll up to 500 dice with up to 500 faces at once!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:465
|
||||
#: albatrobot.py:479
|
||||
#, python-brace-format
|
||||
msgid "{user_name} rolled {rolls} = {result}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:473
|
||||
#: albatrobot.py:487
|
||||
msgid "You used a wrong syntax!"
|
||||
msgstr ""
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# Albatrobot translation.
|
||||
# Copyright (C) 2021 bursa-pastoris
|
||||
# Copyright (C) 2021, 2023 bursa-pastoris
|
||||
# This file is distributed under the same license as the Albatrobot package.
|
||||
# bursa-pastoris <bursapastoris at disroot dot org>, 2021, 2023.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 0.3\n"
|
||||
"Project-Id-Version: Albatrobot 0.4.0-alhpa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-23 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-03-0 00:00+0000\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:00+0000\n"
|
||||
"PO-Revision-Date: 2023-06-11 00:00+0000\n"
|
||||
"Last-Translator: bursa-pastoris <bursapastoris at disroot dot org>\n"
|
||||
"Language-Team: Italian <bursapastoris at disroot dot org>\n"
|
||||
"Language: it\n"
|
||||
|
@ -16,55 +16,55 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: main.py:48 main.py:60 albatrobot.py:161
|
||||
#: main.py:46 main.py:58 albatrobot.py:156
|
||||
msgid "stop"
|
||||
msgstr "stop"
|
||||
|
||||
#: main.py:48 main.py:69 albatrobot.py:159
|
||||
#: main.py:46 main.py:67 albatrobot.py:154
|
||||
msgid "init"
|
||||
msgstr "imposta"
|
||||
|
||||
#: main.py:65 albatrobot.py:143
|
||||
#: main.py:63 albatrobot.py:139 albatrobot.py:191
|
||||
msgid "help"
|
||||
msgstr "aiuto"
|
||||
|
||||
#: main.py:73 albatrobot.py:144
|
||||
#: main.py:71 albatrobot.py:140
|
||||
msgid "legal"
|
||||
msgstr "burocrazia"
|
||||
|
||||
#: main.py:77 albatrobot.py:148
|
||||
#: main.py:75 albatrobot.py:144
|
||||
msgid "version"
|
||||
msgstr "versione"
|
||||
|
||||
#: main.py:84 albatrobot.py:136
|
||||
#: main.py:82 albatrobot.py:132 albatrobot.py:188
|
||||
msgid "christmas"
|
||||
msgstr "natale"
|
||||
|
||||
#: main.py:88 albatrobot.py:137
|
||||
#: main.py:86 albatrobot.py:133 albatrobot.py:189
|
||||
msgid "easter"
|
||||
msgstr "pasqua"
|
||||
|
||||
#: main.py:92
|
||||
#: main.py:90 albatrobot.py:190
|
||||
msgid "end_of_year_dinner"
|
||||
msgstr "cenone_di_fine_anno"
|
||||
|
||||
#: main.py:96 albatrobot.py:141
|
||||
#: main.py:94 albatrobot.py:137
|
||||
msgid "epiphony"
|
||||
msgstr "epifonia"
|
||||
|
||||
#: main.py:100 albatrobot.py:145 albatrobot.py:196
|
||||
#: main.py:98 albatrobot.py:141
|
||||
msgid "roll"
|
||||
msgstr "tira"
|
||||
|
||||
#: albatrobot.py:81
|
||||
#: albatrobot.py:77
|
||||
msgid "User not authorized."
|
||||
msgstr "Utente non autorizzato."
|
||||
|
||||
#: albatrobot.py:89
|
||||
#: albatrobot.py:85
|
||||
msgid "Unknown command."
|
||||
msgstr "Comando sconosciuto."
|
||||
|
||||
#: albatrobot.py:103
|
||||
#: albatrobot.py:99
|
||||
msgid ""
|
||||
"Hello, I'm Albatrobot\\! Type \\/help for help\\!\n"
|
||||
"\n"
|
||||
|
@ -82,23 +82,23 @@ msgstr ""
|
|||
"pubblicamente disponibile su [Disroot](https:\\/\\/git.disroot.org\\/"
|
||||
"bursapastoris\\/albatrobot)\\._"
|
||||
|
||||
#: albatrobot.py:121
|
||||
#: albatrobot.py:117
|
||||
msgid "Albatrobot will be stopped in a few moments."
|
||||
msgstr "L'Albatrobot sarà arrestato tra un istante."
|
||||
|
||||
#: albatrobot.py:134
|
||||
#: albatrobot.py:130
|
||||
msgid "*Albatrobot commands*"
|
||||
msgstr "*Comandi dell'Albatrobot*"
|
||||
|
||||
#: albatrobot.py:136
|
||||
#: albatrobot.py:132
|
||||
msgid "get an image"
|
||||
msgstr "ricevi un'immagine"
|
||||
|
||||
#: albatrobot.py:137
|
||||
#: albatrobot.py:133
|
||||
msgid " `\\(\\<author\\>\\)`"
|
||||
msgstr " `\\(\\<autore\\>\\)`"
|
||||
|
||||
#: albatrobot.py:137
|
||||
#: albatrobot.py:133
|
||||
msgid ""
|
||||
"get a citation from given author, or a random one if no author is "
|
||||
"specified\\."
|
||||
|
@ -106,36 +106,36 @@ msgstr ""
|
|||
"ricevi una citazione dall'autore indicato, o da uno casuale se non viene "
|
||||
"specificato nessun autore\\."
|
||||
|
||||
#: albatrobot.py:139
|
||||
#: albatrobot.py:135
|
||||
msgid "end\\_of\\_year\\_dinner"
|
||||
msgstr "cenone\\_di\\_fine\\_anno"
|
||||
|
||||
#: albatrobot.py:139
|
||||
#: albatrobot.py:135
|
||||
msgid "send all citations in the archive to a random user\\."
|
||||
msgstr "invia tutte le citazioni nell'archivio a un utente casuale\\."
|
||||
|
||||
#: albatrobot.py:141
|
||||
msgid " `\\(\\<text\\>\\)`"
|
||||
msgstr " `\\(\\testo\\>\\)`"
|
||||
#: albatrobot.py:137
|
||||
msgid " `<text\\>`"
|
||||
msgstr " `<testo\\>`"
|
||||
|
||||
#: albatrobot.py:141
|
||||
#: albatrobot.py:137
|
||||
msgid "get a voice message from Albatrobot reading given text"
|
||||
msgstr ""
|
||||
"ricevi un messaggio vocale dall'Albatrobot che legge il testo specificato"
|
||||
|
||||
#: albatrobot.py:143
|
||||
#: albatrobot.py:139
|
||||
msgid "get help about bot commands\\."
|
||||
msgstr "ricevi aiuto sui comandi del bot\\."
|
||||
|
||||
#: albatrobot.py:144
|
||||
#: albatrobot.py:140
|
||||
msgid "get legal info about privacy and copyright\\."
|
||||
msgstr "ricevi informazioni legali su riservatezza e diritto d'autore\\."
|
||||
|
||||
#: albatrobot.py:145
|
||||
#: albatrobot.py:141
|
||||
msgid " `\\<dice\\>\\(\\<modifiers\\>\\)`"
|
||||
msgstr " `\\dadi\\>\\(\\<modificatori\\>\\)`"
|
||||
|
||||
#: albatrobot.py:145
|
||||
#: albatrobot.py:141
|
||||
msgid ""
|
||||
"roll dice, with or without modifiers\\. Launch without arguments to get help "
|
||||
"on the modifiers\\."
|
||||
|
@ -143,15 +143,15 @@ msgstr ""
|
|||
"tira dei dadi, con o senza modificatori\\. Lancia senza argomenti per "
|
||||
"ricevere aiuto sui modificatori\\."
|
||||
|
||||
#: albatrobot.py:148
|
||||
#: albatrobot.py:144
|
||||
msgid "get Albatrobot's version"
|
||||
msgstr "ricevi la versione dell'Albatrobot"
|
||||
|
||||
#: albatrobot.py:157
|
||||
#: albatrobot.py:152
|
||||
msgid "*Additional commands for bot admins*"
|
||||
msgstr "*Comandi aggiuntivi per gli amministratori del bot*"
|
||||
|
||||
#: albatrobot.py:159
|
||||
#: albatrobot.py:154
|
||||
msgid ""
|
||||
"reinitialize the bot\\. This updates inline suggestions and purges /epiphony "
|
||||
"cached files\\."
|
||||
|
@ -159,16 +159,16 @@ msgstr ""
|
|||
"reimposta il bot\\. Questo aggiorna i suggerimenti in linea e rimuove i "
|
||||
"documenti conservati per /epifonia\\."
|
||||
|
||||
#: albatrobot.py:161
|
||||
#: albatrobot.py:156
|
||||
msgid ""
|
||||
"stop Albatrobot\\. To be used _only_ in case of emergency: restarting the "
|
||||
"bot after this command is used requires direct access to the server\\."
|
||||
msgstr ""
|
||||
"arresta l'ALbatrobot\\. Da usare _solo_ in caso di emergenza: riavviare il "
|
||||
"arresta l'Albatrobot\\. Da usare _solo_ in caso di emergenza: riavviare il "
|
||||
"bot dopo che questo comando è stato utilizzato richiede accesso diretto al "
|
||||
"server\\."
|
||||
|
||||
#: albatrobot.py:173
|
||||
#: albatrobot.py:167
|
||||
msgid ""
|
||||
"Bot admins have access to additional commands and can get help on them "
|
||||
"using /help in a private chat\\."
|
||||
|
@ -176,45 +176,63 @@ msgstr ""
|
|||
"Gli amministratori del bot hanno accesso a comandi aggiuntivi e possono "
|
||||
"ricevere aiuto su di essi usando /aiuto in una conversazione privata\\."
|
||||
|
||||
#: albatrobot.py:182
|
||||
#, python-brace-format
|
||||
#: albatrobot.py:174
|
||||
msgid ""
|
||||
"{ccom_help}\n"
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{acom_help}"
|
||||
"{adm_help}"
|
||||
msgstr ""
|
||||
"{ccom_help}\n"
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{acom_help}"
|
||||
"{adm_help}"
|
||||
|
||||
#: albatrobot.py:176
|
||||
msgid ""
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{nonadm_addendum}"
|
||||
msgstr ""
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{nonadm_addendum}"
|
||||
|
||||
#: albatrobot.py:188
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{ccom_help}\n"
|
||||
"\n"
|
||||
"{non_admin_addendum}"
|
||||
msgstr ""
|
||||
"{ccom_help}\n"
|
||||
"\n"
|
||||
"{non_admin_addendum}"
|
||||
msgid "Get an image"
|
||||
msgstr "Ricevi un'immagine"
|
||||
|
||||
#: albatrobot.py:196
|
||||
msgid "Roll dice"
|
||||
msgstr "Tira dei dadi"
|
||||
#: albatrobot.py:189
|
||||
msgid "Get a citation"
|
||||
msgstr "Ricevi una citazione"
|
||||
|
||||
#: albatrobot.py:199
|
||||
#: albatrobot.py:190
|
||||
msgid "Send all citations to a random user"
|
||||
msgstr "Invia tutte le citazioni a un utente casuale"
|
||||
|
||||
#: albatrobot.py:191
|
||||
msgid "Get help"
|
||||
msgstr "Ricevi aiuto"
|
||||
|
||||
#: albatrobot.py:194
|
||||
msgid "Initializing..."
|
||||
msgstr "Reimpostazione in corso..."
|
||||
|
||||
#: albatrobot.py:203
|
||||
#: albatrobot.py:198
|
||||
msgid "Done"
|
||||
msgstr "Fatto"
|
||||
|
||||
#: albatrobot.py:228
|
||||
#: albatrobot.py:217
|
||||
msgid ""
|
||||
"The only official version is the English one and any imperfect translation "
|
||||
"would be misleading. Therefore, this document will not be translated."
|
||||
msgstr ""
|
||||
"L'unica versione ufficiale è quella inglese e qualunque traduzione "
|
||||
"imperfetta sarebbe fuorviante. Pertanto, questo documento non sarà tradotto."
|
||||
|
||||
#: albatrobot.py:227
|
||||
msgid "*Albatrobot's version:* {}"
|
||||
msgstr "*Versione dell'Albatrobot:* {}"
|
||||
|
||||
#: albatrobot.py:242
|
||||
#: albatrobot.py:240
|
||||
msgid ""
|
||||
"Christmas is good, but you can't invoke it so often! Try again in some "
|
||||
"seconds..."
|
||||
|
@ -222,22 +240,22 @@ msgstr ""
|
|||
"Il Natale è bello, ma non puoi invocarlo così spesso! RIprova tra qualche "
|
||||
"secondo..."
|
||||
|
||||
#: albatrobot.py:273
|
||||
#: albatrobot.py:274
|
||||
msgid ""
|
||||
"Easter is good, but you can't invoke it so often! Retry in some seconds..."
|
||||
msgstr ""
|
||||
"La Pasqua è bella, ma non puoi invocarla così spesso! Riprova tra qualche "
|
||||
"secondo..."
|
||||
|
||||
#: albatrobot.py:296
|
||||
#: albatrobot.py:293
|
||||
msgid "The most similar is {}."
|
||||
msgstr "Il più simile è {}."
|
||||
|
||||
#: albatrobot.py:300
|
||||
#: albatrobot.py:297
|
||||
msgid "The most similar are {} and {}."
|
||||
msgstr "I più simili sono {} e {}."
|
||||
|
||||
#: albatrobot.py:304
|
||||
#: albatrobot.py:301
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Author {required_author} is not present in the archive! {suggestion}\n"
|
||||
|
@ -248,7 +266,7 @@ msgstr ""
|
|||
"\n"
|
||||
"N.b.: Le MaIuScOlE sOnO iMpOrTaNtI!"
|
||||
|
||||
#: albatrobot.py:324 albatrobot.py:352
|
||||
#: albatrobot.py:321 albatrobot.py:347
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{cit}\n"
|
||||
|
@ -259,113 +277,118 @@ msgstr ""
|
|||
"\n"
|
||||
"~{author}"
|
||||
|
||||
#: albatrobot.py:345
|
||||
#: albatrobot.py:340
|
||||
msgid "Hello there, here an end of year dinner offered by {}!"
|
||||
msgstr "Ciao, ecco un cenone di fine anno offerta da {}!"
|
||||
|
||||
#: albatrobot.py:359
|
||||
#: albatrobot.py:354
|
||||
#, python-brace-format
|
||||
msgid "End of year dinner of {cits_number} plates delvered to {dest}!"
|
||||
msgstr "Cenone di fine anno di {cits_number} portate consegnato a {dest}!"
|
||||
|
||||
#: albatrobot.py:372
|
||||
#: albatrobot.py:368
|
||||
msgid "What should I say?"
|
||||
msgstr "Cosa dovrei dire?"
|
||||
|
||||
#: albatrobot.py:402
|
||||
#: albatrobot.py:391
|
||||
#, python-brace-format
|
||||
msgid "Voice message from {sender_name}."
|
||||
msgstr "Messaggio vocale da {sender_name}."
|
||||
|
||||
#: albatrobot.py:416
|
||||
msgid "add `n` to the roll"
|
||||
msgstr "aggiungi `n` al tiro"
|
||||
|
||||
#: albatrobot.py:403
|
||||
#: albatrobot.py:417
|
||||
msgid "subtract `n` from the roll"
|
||||
msgstr "sottrati `n` dal tiro"
|
||||
|
||||
#: albatrobot.py:404
|
||||
#: albatrobot.py:418
|
||||
msgid "multiply the roll by `n`"
|
||||
msgstr "moltiplica il tiro per `n`"
|
||||
|
||||
#: albatrobot.py:405
|
||||
#: albatrobot.py:419
|
||||
msgid "divide the roll by `n`"
|
||||
msgstr "dividi il tiro per `n`"
|
||||
|
||||
#: albatrobot.py:406
|
||||
#: albatrobot.py:420
|
||||
msgid "floor divide the roll by `n`"
|
||||
msgstr "ottieni il quoto del tiro diviso per `n`"
|
||||
|
||||
#: albatrobot.py:407
|
||||
#: albatrobot.py:421
|
||||
msgid "exponentiate the roll to `n`"
|
||||
msgstr "eleva il tiro alla potenza `n`"
|
||||
|
||||
#: albatrobot.py:408
|
||||
#: albatrobot.py:422
|
||||
msgid "keep highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr "tieni gli `n` tiri più alti \\(valore predefinito: `1`\\)"
|
||||
|
||||
#: albatrobot.py:409
|
||||
#: albatrobot.py:423
|
||||
msgid "keep lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr "tieni gli `n` tiri più bassi \\(valore predefinito: `1`\\)"
|
||||
|
||||
#: albatrobot.py:410
|
||||
#: albatrobot.py:424
|
||||
msgid "drop highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr "scarta gli `n` tiri più alti \\(valore predefinito: `1`\\)"
|
||||
|
||||
#: albatrobot.py:411
|
||||
#: albatrobot.py:425
|
||||
msgid "drop lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr "scarta gli `n` tiri più bassi \\(valore predefinito: `1`\\)"
|
||||
|
||||
#: albatrobot.py:412
|
||||
#: albatrobot.py:426
|
||||
msgid "explode rolls equal to `n` \\(defaults to die size\\)"
|
||||
msgstr ""
|
||||
"fai esplodere i tiri pari a `n` \\(valore predefinito: dimensione del dado\\)"
|
||||
|
||||
#: albatrobot.py:413
|
||||
#: albatrobot.py:427
|
||||
msgid "explode rolls lower than `n`"
|
||||
msgstr "fai esplodere i tiri minori di `n`"
|
||||
|
||||
#: albatrobot.py:414
|
||||
#: albatrobot.py:428
|
||||
msgid "explode rolls higher than `n`"
|
||||
msgstr "fai esplodere i tiri maggiori di `n`"
|
||||
|
||||
#: albatrobot.py:415
|
||||
#: albatrobot.py:429
|
||||
msgid "count failures as rolls lower than `n`"
|
||||
msgstr "conta i fallimenti come i tiri minori di `n`"
|
||||
|
||||
#: albatrobot.py:416
|
||||
#: albatrobot.py:430
|
||||
msgid "count failures as rolls higher than `n`"
|
||||
msgstr "conta i fallimenti come i tiri maggiori di `n`"
|
||||
|
||||
#: albatrobot.py:417
|
||||
#: albatrobot.py:431
|
||||
msgid "count successes as rolls lower than `n`"
|
||||
msgstr "conta i successi come i tiri minori di `n`"
|
||||
|
||||
#: albatrobot.py:418
|
||||
#: albatrobot.py:432
|
||||
msgid "count successes as rolls higher than `n`"
|
||||
msgstr "conta i successi come i tiri maggiori di `n`"
|
||||
|
||||
#: albatrobot.py:419
|
||||
#: albatrobot.py:433
|
||||
msgid "penetrate rolls equal to dice size"
|
||||
msgstr "penetra i tiri pari alla dimensione del dado"
|
||||
|
||||
#: albatrobot.py:420
|
||||
#: albatrobot.py:434
|
||||
msgid "penetrate rolls lower than `n`"
|
||||
msgstr "penetra i tiri minori di `n`"
|
||||
|
||||
#: albatrobot.py:421
|
||||
#: albatrobot.py:435
|
||||
msgid "penetrate rolls higher than `n`"
|
||||
msgstr "penetra i tiri maggiori di `n`"
|
||||
|
||||
#: albatrobot.py:422
|
||||
#: albatrobot.py:436
|
||||
msgid "add `n` to each roll"
|
||||
msgstr "aggiungi `n` a ogni tiro"
|
||||
|
||||
#: albatrobot.py:423
|
||||
#: albatrobot.py:437
|
||||
msgid "subtract `n` from each roll"
|
||||
msgstr "sottrai `n` a ogni tiro"
|
||||
|
||||
#: albatrobot.py:424
|
||||
#: albatrobot.py:438
|
||||
msgid "multiply by `n` each roll"
|
||||
msgstr "moltiplica ogni tiro per `n`"
|
||||
|
||||
#: albatrobot.py:425
|
||||
#: albatrobot.py:439
|
||||
msgid ""
|
||||
"reroll each dice that rolled `n` until there are no `n` left\\(defaults to "
|
||||
"`1`\\)"
|
||||
|
@ -373,12 +396,12 @@ msgstr ""
|
|||
"ritira ogni dado con risultato `n` finché non ci sono `n` rimanenti "
|
||||
"\\(valore predefinito: `1`\\)"
|
||||
|
||||
#: albatrobot.py:427
|
||||
#: albatrobot.py:441
|
||||
msgid "reroll once each dice that rolled `n` \\(defaults to 1\\)"
|
||||
msgstr ""
|
||||
"ritira una volta ogni dado che con risultato `n` \\(valore predefinito: 1\\)"
|
||||
|
||||
#: albatrobot.py:429
|
||||
#: albatrobot.py:443
|
||||
msgid ""
|
||||
"reroll dice that rolled lower than `n` until there are no results lower than "
|
||||
"`n` left"
|
||||
|
@ -386,7 +409,7 @@ msgstr ""
|
|||
"ritira i dadi con risultato minore di `n` finché non ci sono risultati "
|
||||
"minori di `n` rimanenti"
|
||||
|
||||
#: albatrobot.py:431
|
||||
#: albatrobot.py:445
|
||||
msgid ""
|
||||
"reroll dice that rolled higher than `n` until there no results higher than "
|
||||
"`n` left"
|
||||
|
@ -394,15 +417,15 @@ msgstr ""
|
|||
"ritira i dadi con risultato maggiore di `n` finché non ci sono risultati "
|
||||
"maggiori di `n` rimanenti"
|
||||
|
||||
#: albatrobot.py:433
|
||||
#: albatrobot.py:447
|
||||
msgid "reroll once dice that roll lower than `n`"
|
||||
msgstr "ritira una volta i dadi con risultati minore di `n`"
|
||||
|
||||
#: albatrobot.py:434
|
||||
#: albatrobot.py:448
|
||||
msgid "reroll once dice that roll higher than `n`"
|
||||
msgstr "ritira una volta i dadi con risultato maggiore di `n`"
|
||||
|
||||
#: albatrobot.py:439
|
||||
#: albatrobot.py:453
|
||||
msgid ""
|
||||
"To roll, use the syntax `\\<number of dice\\>d\\<dice size\\>`\\. You can "
|
||||
"also use the following modifiers\\. Note that:\n"
|
||||
|
@ -421,15 +444,18 @@ msgstr ""
|
|||
"\n"
|
||||
"\n"
|
||||
|
||||
#: albatrobot.py:458
|
||||
#: albatrobot.py:472
|
||||
msgid "You can roll up to 500 dice with up to 500 faces at once!"
|
||||
msgstr "Puoi tirare al massimo 1000 dadi con al massimo 1000 facce per volta!"
|
||||
msgstr "Puoi tirare al massimo 500 dadi con al massimo 500 facce per volta!"
|
||||
|
||||
#: albatrobot.py:465
|
||||
#: albatrobot.py:479
|
||||
#, python-brace-format
|
||||
msgid "{user_name} rolled {rolls} = {result}"
|
||||
msgstr "{user_name} ha tirato {rolls} = {result}"
|
||||
|
||||
#: albatrobot.py:473
|
||||
#: albatrobot.py:487
|
||||
msgid "You used a wrong syntax!"
|
||||
msgstr "Hai usato una sintassi errata!"
|
||||
|
||||
#~ msgid "Roll dice"
|
||||
#~ msgstr "Tira dei dadi"
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Albatrobot 0.3\n"
|
||||
"Project-Id-Version: Albatrobot v0.4.0-alpha\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-03-23 00:00+0000\n"
|
||||
"POT-Creation-Date: 2023-06-11 00:00+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,55 +17,55 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: main.py:48 main.py:60 albatrobot.py:161
|
||||
#: main.py:46 main.py:58 albatrobot.py:156
|
||||
msgid "stop"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:48 main.py:69 albatrobot.py:159
|
||||
#: main.py:46 main.py:67 albatrobot.py:154
|
||||
msgid "init"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:65 albatrobot.py:143
|
||||
#: main.py:63 albatrobot.py:139 albatrobot.py:191
|
||||
msgid "help"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:73 albatrobot.py:144
|
||||
#: main.py:71 albatrobot.py:140
|
||||
msgid "legal"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:77 albatrobot.py:148
|
||||
#: main.py:75 albatrobot.py:144
|
||||
msgid "version"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:84 albatrobot.py:136
|
||||
#: main.py:82 albatrobot.py:132 albatrobot.py:188
|
||||
msgid "christmas"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:88 albatrobot.py:137
|
||||
#: main.py:86 albatrobot.py:133 albatrobot.py:189
|
||||
msgid "easter"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:92
|
||||
#: main.py:90 albatrobot.py:190
|
||||
msgid "end_of_year_dinner"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:96 albatrobot.py:141
|
||||
#: main.py:94 albatrobot.py:137
|
||||
msgid "epiphony"
|
||||
msgstr ""
|
||||
|
||||
#: main.py:100 albatrobot.py:145 albatrobot.py:196
|
||||
#: main.py:98 albatrobot.py:141
|
||||
msgid "roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:81
|
||||
#: albatrobot.py:77
|
||||
msgid "User not authorized."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:89
|
||||
#: albatrobot.py:85
|
||||
msgid "Unknown command."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:103
|
||||
#: albatrobot.py:99
|
||||
msgid ""
|
||||
"Hello, I'm Albatrobot\\! Type \\/help for help\\!\n"
|
||||
"\n"
|
||||
|
@ -76,140 +76,158 @@ msgid ""
|
|||
"albatrobot)\\._"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:121
|
||||
#: albatrobot.py:117
|
||||
msgid "Albatrobot will be stopped in a few moments."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:134
|
||||
#: albatrobot.py:130
|
||||
msgid "*Albatrobot commands*"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:136
|
||||
#: albatrobot.py:132
|
||||
msgid "get an image"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:137
|
||||
#: albatrobot.py:133
|
||||
msgid " `\\(\\<author\\>\\)`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:137
|
||||
#: albatrobot.py:133
|
||||
msgid ""
|
||||
"get a citation from given author, or a random one if no author is "
|
||||
"specified\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:139
|
||||
#: albatrobot.py:135
|
||||
msgid "end\\_of\\_year\\_dinner"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:139
|
||||
#: albatrobot.py:135
|
||||
msgid "send all citations in the archive to a random user\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:141
|
||||
msgid " `\\(\\<text\\>\\)`"
|
||||
#: albatrobot.py:137
|
||||
msgid " `<text\\>`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:141
|
||||
#: albatrobot.py:137
|
||||
msgid "get a voice message from Albatrobot reading given text"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:143
|
||||
#: albatrobot.py:139
|
||||
msgid "get help about bot commands\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:144
|
||||
#: albatrobot.py:140
|
||||
msgid "get legal info about privacy and copyright\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:145
|
||||
#: albatrobot.py:141
|
||||
msgid " `\\<dice\\>\\(\\<modifiers\\>\\)`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:145
|
||||
#: albatrobot.py:141
|
||||
msgid ""
|
||||
"roll dice, with or without modifiers\\. Launch without arguments to get help "
|
||||
"on the modifiers\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:148
|
||||
#: albatrobot.py:144
|
||||
msgid "get Albatrobot's version"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:157
|
||||
#: albatrobot.py:152
|
||||
msgid "*Additional commands for bot admins*"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:159
|
||||
#: albatrobot.py:154
|
||||
msgid ""
|
||||
"reinitialize the bot\\. This updates inline suggestions and purges /epiphony "
|
||||
"cached files\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:161
|
||||
#: albatrobot.py:156
|
||||
msgid ""
|
||||
"stop Albatrobot\\. To be used _only_ in case of emergency: restarting the "
|
||||
"bot after this command is used requires direct access to the server\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:173
|
||||
#: albatrobot.py:167
|
||||
msgid ""
|
||||
"Bot admins have access to additional commands and can get help on them "
|
||||
"using /help in a private chat\\."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:182
|
||||
#: albatrobot.py:174
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{ccom_help}\n"
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{acom_help}"
|
||||
"{adm_help}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:176
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{com_help}\n"
|
||||
"\n"
|
||||
"{nonadm_addendum}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:188
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{ccom_help}\n"
|
||||
"\n"
|
||||
"{non_admin_addendum}"
|
||||
msgid "Get an image"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:196
|
||||
msgid "Roll dice"
|
||||
#: albatrobot.py:189
|
||||
msgid "Get a citation"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:199
|
||||
#: albatrobot.py:190
|
||||
msgid "Send all citations to a random user"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:191
|
||||
msgid "Get help"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:194
|
||||
msgid "Initializing..."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:203
|
||||
#: albatrobot.py:198
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:228
|
||||
#: albatrobot.py:217
|
||||
msgid ""
|
||||
"The only official version is the English one and any imperfect translation "
|
||||
"would be misleading. Therefore, this document will not be translated."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:227
|
||||
msgid "*Albatrobot's version:* {}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:242
|
||||
#: albatrobot.py:240
|
||||
msgid ""
|
||||
"Christmas is good, but you can't invoke it so often! Try again in some "
|
||||
"seconds..."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:273
|
||||
#: albatrobot.py:274
|
||||
msgid ""
|
||||
"Easter is good, but you can't invoke it so often! Retry in some seconds..."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:296
|
||||
#: albatrobot.py:293
|
||||
msgid "The most similar is {}."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:300
|
||||
#: albatrobot.py:297
|
||||
msgid "The most similar are {} and {}."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:304
|
||||
#: albatrobot.py:301
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Author {required_author} is not present in the archive! {suggestion}\n"
|
||||
|
@ -217,7 +235,7 @@ msgid ""
|
|||
"N.b.: CaSe Is ImPoRtAnT!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:324 albatrobot.py:352
|
||||
#: albatrobot.py:321 albatrobot.py:347
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{cit}\n"
|
||||
|
@ -225,142 +243,147 @@ msgid ""
|
|||
"~{author}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:345
|
||||
#: albatrobot.py:340
|
||||
msgid "Hello there, here an end of year dinner offered by {}!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:359
|
||||
#: albatrobot.py:354
|
||||
#, python-brace-format
|
||||
msgid "End of year dinner of {cits_number} plates delvered to {dest}!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:372
|
||||
#: albatrobot.py:368
|
||||
msgid "What should I say?"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:402
|
||||
msgid "add `n` to the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:403
|
||||
msgid "subtract `n` from the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:404
|
||||
msgid "multiply the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:405
|
||||
msgid "divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:406
|
||||
msgid "floor divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:407
|
||||
msgid "exponentiate the roll to `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:408
|
||||
msgid "keep highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:409
|
||||
msgid "keep lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:410
|
||||
msgid "drop highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:411
|
||||
msgid "drop lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:412
|
||||
msgid "explode rolls equal to `n` \\(defaults to die size\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:413
|
||||
msgid "explode rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:414
|
||||
msgid "explode rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:415
|
||||
msgid "count failures as rolls lower than `n`"
|
||||
#: albatrobot.py:391
|
||||
#, python-brace-format
|
||||
msgid "Voice message from {sender_name}."
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:416
|
||||
msgid "count failures as rolls higher than `n`"
|
||||
msgid "add `n` to the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:417
|
||||
msgid "count successes as rolls lower than `n`"
|
||||
msgid "subtract `n` from the roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:418
|
||||
msgid "count successes as rolls higher than `n`"
|
||||
msgid "multiply the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:419
|
||||
msgid "penetrate rolls equal to dice size"
|
||||
msgid "divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:420
|
||||
msgid "penetrate rolls lower than `n`"
|
||||
msgid "floor divide the roll by `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:421
|
||||
msgid "penetrate rolls higher than `n`"
|
||||
msgid "exponentiate the roll to `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:422
|
||||
msgid "add `n` to each roll"
|
||||
msgid "keep highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:423
|
||||
msgid "subtract `n` from each roll"
|
||||
msgid "keep lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:424
|
||||
msgid "multiply by `n` each roll"
|
||||
msgid "drop highest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:425
|
||||
msgid "drop lowest `n` rolls \\(defaults to `1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:426
|
||||
msgid "explode rolls equal to `n` \\(defaults to die size\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:427
|
||||
msgid "explode rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:428
|
||||
msgid "explode rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:429
|
||||
msgid "count failures as rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:430
|
||||
msgid "count failures as rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:431
|
||||
msgid "count successes as rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:432
|
||||
msgid "count successes as rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:433
|
||||
msgid "penetrate rolls equal to dice size"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:434
|
||||
msgid "penetrate rolls lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:435
|
||||
msgid "penetrate rolls higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:436
|
||||
msgid "add `n` to each roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:437
|
||||
msgid "subtract `n` from each roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:438
|
||||
msgid "multiply by `n` each roll"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:439
|
||||
msgid ""
|
||||
"reroll each dice that rolled `n` until there are no `n` left\\(defaults to "
|
||||
"`1`\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:427
|
||||
#: albatrobot.py:441
|
||||
msgid "reroll once each dice that rolled `n` \\(defaults to 1\\)"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:429
|
||||
#: albatrobot.py:443
|
||||
msgid ""
|
||||
"reroll dice that rolled lower than `n` until there are no results lower than "
|
||||
"`n` left"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:431
|
||||
#: albatrobot.py:445
|
||||
msgid ""
|
||||
"reroll dice that rolled higher than `n` until there no results higher than "
|
||||
"`n` left"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:433
|
||||
#: albatrobot.py:447
|
||||
msgid "reroll once dice that roll lower than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:434
|
||||
#: albatrobot.py:448
|
||||
msgid "reroll once dice that roll higher than `n`"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:439
|
||||
#: albatrobot.py:453
|
||||
msgid ""
|
||||
"To roll, use the syntax `\\<number of dice\\>d\\<dice size\\>`\\. You can "
|
||||
"also use the following modifiers\\. Note that:\n"
|
||||
|
@ -372,15 +395,15 @@ msgid ""
|
|||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:458
|
||||
#: albatrobot.py:472
|
||||
msgid "You can roll up to 500 dice with up to 500 faces at once!"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:465
|
||||
#: albatrobot.py:479
|
||||
#, python-brace-format
|
||||
msgid "{user_name} rolled {rolls} = {result}"
|
||||
msgstr ""
|
||||
|
||||
#: albatrobot.py:473
|
||||
#: albatrobot.py:487
|
||||
msgid "You used a wrong syntax!"
|
||||
msgstr ""
|
||||
|
|
40
main.py
40
main.py
|
@ -1,23 +1,21 @@
|
|||
#!/bin/python3
|
||||
|
||||
"""
|
||||
Albatrobot - Telegram bot for RPG groups and similar
|
||||
Copyright (C) 2019, 2020, 2021, 2022 bursa-pastoris
|
||||
|
||||
This file is part of Albatrobot.
|
||||
|
||||
Albatrobot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, version 3 of the License.
|
||||
|
||||
Albatrobot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with Albatrobot. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
# Albatrobot - Telegram bot for RPG groups and similar
|
||||
# Copyright (C) 2019, 2020, 2021, 2022, 2023 bursa-pastoris
|
||||
#
|
||||
# This file is part of Albatrobot.
|
||||
#
|
||||
# Albatrobot is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Albatrobot is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with Albatrobot. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import gettext
|
||||
from telegram import Update
|
||||
|
@ -45,7 +43,7 @@ application.add_handler(
|
|||
albatrobot.unauthorized_user)
|
||||
)
|
||||
application.add_handler(
|
||||
CommandHandler(['stop',_('stop'),'init',_('init')],
|
||||
CommandHandler(['stop',_('stop'),'reset',_('reset')],
|
||||
albatrobot.unauthorized_user,
|
||||
(~filters.User(ADMINS)))
|
||||
)
|
||||
|
@ -66,8 +64,8 @@ application.add_handler(
|
|||
albatrobot.help)
|
||||
)
|
||||
application.add_handler(
|
||||
CommandHandler(['init',_('init')],
|
||||
albatrobot.init)
|
||||
CommandHandler(['reset',_('reset')],
|
||||
albatrobot.reset)
|
||||
)
|
||||
application.add_handler(
|
||||
CommandHandler(['legal',_('legal')],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
python-telegram-bot[socks]~=20.0
|
||||
python-telegram-bot[socks]~=20.3
|
||||
|
||||
Levenshtein~=0.21
|
||||
psutil~=5.9
|
||||
py-rolldice~=0.4
|
||||
python-Levenshtein~=0.12
|
||||
pyttsx3~=2.90
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
ID,author,text,year,place
|
||||
ABT-0001,Albatrobot,No citations available,2022,
|
||||
ABT-0002,Albatrobot,"No citations available, I said!",,Brescia
|
||||
ID,author,text
|
||||
ABT-0001,Albatrobot,No citations available
|
||||
|
|
|
|
@ -0,0 +1,2 @@
|
|||
filename,caption
|
||||
no-images-available.png,No images available
|
|
Binary file not shown.
Before Width: | Height: | Size: 242 KiB |
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -7,10 +7,11 @@ Admins:
|
|||
|
||||
[Settings]
|
||||
Language:
|
||||
MsgCooldown: 5
|
||||
ChristmasCooldown: 5
|
||||
EasterCooldown: 5
|
||||
Proxy:
|
||||
YellLang:
|
||||
YellSpeed: 120
|
||||
EpiphonyLang:
|
||||
EpiphonySpeed: 120
|
||||
|
||||
[Resources]
|
||||
CitArchive: resources/citations/citations.csv
|
||||
|
|
Loading…
Reference in New Issue