Compare commits

...

No commits in common. "master-2022-09-27" and "gh-pages" have entirely different histories.

804 changed files with 1437 additions and 164646 deletions

2
.bundle/config Normal file
View File

@ -0,0 +1,2 @@
---
BUNDLE_PATH: "vendor/bundle"

8
.editorconfig Normal file
View File

@ -0,0 +1,8 @@
root = true
[*]
end_of_line = lf
trim_trailing_whitespace = false
insert_final_newline = true
charset = utf-8
indent_style = space

3
.gitattributes vendored
View File

@ -1,2 +1 @@
sandbox export-ignore
.git* export-ignore
* text=auto eol=lf

1
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1 @@
* @Mikaela

30
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,30 @@
version: 2
updates:
- package-ecosystem: "bundler"
directory: "/"
schedule:
interval: "daily"
timezone: "Europe/Helsinki"
groups:
bundler:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
timezone: "Europe/Helsinki"
groups:
github-actions:
patterns:
- "*"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
groups:
npm:
patterns:
- "*"

View File

@ -0,0 +1,25 @@
name: HTML5 Validator
on:
push:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # Required will all actions
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.1
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Jekyll build
run: |
bundle exec jekyll build --drafts --profile
- name: Checks HTML5 validity
uses: Cyb3r-Jak3/html5validator-action@v7.2.0
with:
root: _site/
blacklist: n r or ir

View File

@ -1,54 +0,0 @@
name: Test
on:
push:
pull_request:
jobs:
build:
runs-on: ${{ matrix.runs-on }}
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11.0-rc.2", "pypy-3.6", "pypy-3.7"]
with-opt-deps: [false, true]
runs-on: [ubuntu-latest]
exclude:
# Some of the dependencies don't work on old Python versions
- python-version: "3.6"
with-opt-deps: true
- python-version: "pypy-3.6"
with-opt-deps: true
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Upgrade pip
run: |
python3 -m pip install --upgrade pip
- name: Install optional dependencies
if: ${{ matrix.with-opt-deps }}
run: |
python3 -m pip install --upgrade pip
pip3 install -r requirements.txt
- name: Install
run: |
LIMNORIA_WARN_OLD_PYTHON=0 python3 setup.py install
- name: Test with unittest
run: |
supybot-test test -v --plugins-dir=./plugins/ --no-network
- name: Test with irctest
if: "${{ matrix.with-opt-deps && matrix.python-version != 'pypy-3.7' }}"
run: |
git clone https://github.com/ProgVal/irctest.git
cd irctest
pip3 install -r requirements.txt
make limnoria PYTEST_ARGS=-vs

19
.gitignore vendored
View File

@ -23,18 +23,9 @@ supybot.egg-info/
test-conf/
test-data/
test-logs/
doc-conf/
doc-data/
doc-logs/
src/version.py
INSTALL
README.txt
conf/
data/
logs/
*.conf
*.conf.bak
# Intellij PyCharm / IDEA related files
*.iml
.idea
_site
.sass-cache
vendor/
.bundle
node_modules/

View File

@ -1,27 +0,0 @@
<jamessan@users.sourceforge.net> <vega.james@gmail.com>
<jemfinch@users.sourceforge.net> <jemfinch@finchers.us>
<jemfinch@users.sourceforge.net> <jfincher@monoid.(none)>
<mikaela.suomalainen@outlook.com> <Mkaysi@users.noreply.github.com>
<nyuszika7h@openmailbox.org> <liemininyuszika@gmail.com>
<nyuszika7h@openmailbox.org> <litemininyuszika@gmail.com>
<nyuszika7h@openmailbox.org> <nyuszika7h@cadoth.co>
<nyuszika7h@openmailbox.org> <nyuszika7h@cadoth.net>
<nyuszika7h@openmailbox.org> <nyuszika7h@gmail.com>
<nyuszika7h@openmailbox.org> <nyuszika7h@outlook.com>
<progval@progval.net> <progval+github@progval.net>
<progval@progval.net> <progval@gmail.com>
<shadowninja@minetest.net> <ShadowNinja@users.noreply.github.com>
Daniel Folkinshteyn <nanotube@users.sourceforge.net> Daniel F <dfolkins@a90.(none)>
Daniel Folkinshteyn <nanotube@users.sourceforge.net> nanotube <nanotube@users.sf.net>
James Lu <james@overdrivenetworks.com> <GLolol1@hotmail.com>
James Lu <james@overdrivenetworks.com> <glolol1@hotmail.com>
James Lu <james@overdrivenetworks.com> <glolol@overdrive.pw>
James Lu <james@overdrivenetworks.com> <GLolol@overdrivenetworks.com>
James McCoy <jamessan@users.sourceforge.net>
Ken Spencer <ken@electrocode.net> Iota Spencer <iota@electrocode.net>
Mikaela Suomalainen <mikaela.suomalainen@outlook.com> Mika Suomalainen <mika.henrik.mainio@hotmail.com>
Mikaela Suomalainen <mikaela.suomalainen@outlook.com> Mika Suomalainen <mkaysi@outlook.com>
Mikaela Suomalainen <mikaela.suomalainen@outlook.com> Mika Suomalainen <mkaysi@users.sourceforge.net>
Mikaela Suomalainen <mikaela.suomalainen@outlook.com> Mika Suomalainen <s.mika95@gmail.com>
Mikaela Suomalainen <mikaela.suomalainen@outlook.com> Mikaela Suomalainen <mkaysi@outlook.com>
Tannn3r <tannn3r@gmail.com> <tanman8r@gmail.com>

76
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,76 @@
# SPDX-FileCopyrightText: 2023 Aminda Suomalainen <suomalainen+git@mikaela.info>
#
# SPDX-License-Identifier: CC0-1.0
# See https://pre-commit.com for more information
# See https://pre-commit.ci for more information
ci:
# I don't need so many duplicated notifications on the same thing as I keep
# autoupdating manually too. Besides it just creates extra branch I never
# touch.
# https://github.com/pre-commit-ci/issues/issues/83
autoupdate_schedule: quarterly
# Use pypy3 for the Python hooks. Except don't, see .gitlab-ci.yml
#default_language_version:
# python: pypy3
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
args: ["--markdown-linebreak-ext", "md,markdown"]
exclude_types: [svg, tsv]
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-json
- id: check-merge-conflict
- id: check-shebang-scripts-are-executable
- id: destroyed-symlinks
- id: detect-private-key
- id: fix-byte-order-marker
- id: check-merge-conflict
- id: mixed-line-ending
args: [--fix=auto]
- id: pretty-format-json
args: [--autofix, --no-ensure-ascii]
- repo: https://github.com/pre-commit-ci/pre-commit-ci-config
rev: v1.6.1
hooks:
- id: check-pre-commit-ci-config
- repo: https://github.com/thlorenz/doctoc
rev: v2.2.0
hooks:
- id: doctoc
args: [--update-only, --notitle]
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.28.4
hooks:
- id: check-dependabot
- id: check-github-workflows
- id: check-gitlab-ci
# - repo: https://github.com/fsfe/reuse-tool
# rev: v3.0.2
# hooks:
# - id: reuse
- repo: https://github.com/rbubley/mirrors-prettier
rev: "v3.3.0"
hooks:
- id: prettier
exclude_types: [json]
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
rev: "2.7.3"
hooks:
- id: editorconfig-checker
alias: ec
args: [-disable-max-line-length]

4
.prettierignore Normal file
View File

@ -0,0 +1,4 @@
_includes/
_layouts/
_sass/
css/

2
.travis.yml Normal file
View File

@ -0,0 +1,2 @@
language: ruby
script: "bundle exec jekyll build"

1
CNAME Normal file
View File

@ -0,0 +1 @@
supybot.mikaela.info

View File

@ -1,37 +0,0 @@
# Contributing to Limnoria
## Guidelines
Follow the [Style Guidelines].
When adding a string that will be shown on IRC, always internationalize
it (wrap it in a call to `_()`).
When making a trivial change to an internationalized string that does not
affect the meaning of the string (typo fix, etc.), please update the
`msgid` entry in localization file. It helps preserve the translation
without the translator having to review it.
Last rule: you shouldn't add a mandatory dependency. Limnoria does not
come with any (besides Python), so please try to keep all dependencies
optional.
[Style Guidelines]:https://limnoria.readthedocs.io/en/latest/develop/style.html
## Sending patches
When you send a pull request, **send it to the testing branch**.
It will be merged to master when it's considered to be stable enough to be
supported.
Don't fear that you spam Limnoria by sending many pull requests. According
to @ProgVal, it's easier for them to accept pull requests than to
cherry-pick everything manually.
Having at least one test case in any non-trivial pull-request
is very appreciated.
See also [Contributing to Limnoria] at [Limnoria documentation].
[Contributing to Limnoria]:https://limnoria.readthedocs.io/en/latest/contribute/index.html
[Limnoria documentation]:https://limnoria.readthedocs.io/

2022
ChangeLog

File diff suppressed because it is too large Load Diff

7
Gemfile Normal file
View File

@ -0,0 +1,7 @@
source "https://rubygems.org"
# For now this is a GitHub Pages hosted website.
# Ref: https://github.com/Mikaela/mikaela.github.io/issues/153
gem 'github-pages', group: :jekyll_plugins
gem 'jekyll-seo-tag'
# Required for `bundle exec jekyll serve`
gem "webrick"

271
Gemfile.lock Normal file
View File

@ -0,0 +1,271 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3.3)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
base64 (0.2.0)
bigdecimal (3.1.8)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
colorator (1.1.0)
commonmarker (0.23.10)
concurrent-ruby (1.3.1)
connection_pool (2.4.1)
dnsruby (1.72.1)
simpleidn (~> 0.2.1)
drb (2.2.1)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
ethon (0.16.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.9.1)
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (3.1.0)
net-http
ffi (1.17.0-x86_64-linux-gnu)
forwardable-extended (2.6.0)
gemoji (4.1.0)
github-pages (231)
github-pages-health-check (= 1.18.2)
jekyll (= 3.9.5)
jekyll-avatar (= 0.8.0)
jekyll-coffeescript (= 1.2.2)
jekyll-commonmark-ghpages (= 0.4.0)
jekyll-default-layout (= 0.1.5)
jekyll-feed (= 0.17.0)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.16.1)
jekyll-include-cache (= 0.2.1)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.8.0)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.2.0)
jekyll-theme-cayman (= 0.2.0)
jekyll-theme-dinky (= 0.2.0)
jekyll-theme-hacker (= 0.2.0)
jekyll-theme-leap-day (= 0.2.0)
jekyll-theme-merlot (= 0.2.0)
jekyll-theme-midnight (= 0.2.0)
jekyll-theme-minimal (= 0.2.0)
jekyll-theme-modernist (= 0.2.0)
jekyll-theme-primer (= 0.6.0)
jekyll-theme-slate (= 0.2.0)
jekyll-theme-tactile (= 0.2.0)
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.13.0)
kramdown (= 2.4.0)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.4)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.13.6, < 2.0)
rouge (= 3.30.0)
terminal-table (~> 1.4)
github-pages-health-check (1.18.2)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (>= 4, < 8)
public_suffix (>= 3.0, < 6.0)
typhoeus (~> 1.3)
html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (1.14.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.5)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (>= 0.7, < 2)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.8.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.2.2)
coffee-script (~> 2.2)
coffee-script-source (~> 1.12)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-commonmark-ghpages (0.4.0)
commonmarker (~> 0.23.7)
jekyll (~> 3.9.0)
jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 5.0)
jekyll-default-layout (0.1.5)
jekyll (>= 3.0, < 5.0)
jekyll-feed (0.17.0)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.16.1)
jekyll (>= 3.4, < 5.0)
octokit (>= 4, < 7, != 4.4.0)
jekyll-include-cache (0.2.1)
jekyll (>= 3.7, < 5.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.13.0)
gemoji (>= 3, < 5)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.23.1)
mutex_m (0.2.0)
net-http (0.4.1)
uri
nokogiri (1.16.5-x86_64-linux)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.0.5)
racc (1.8.0)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rexml (3.2.8)
strscan (>= 3.0.9)
rouge (3.30.0)
rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
simpleidn (0.2.3)
strscan (3.1.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (1.8.0)
uri (0.13.0)
webrick (1.8.1)
PLATFORMS
x86_64-linux
DEPENDENCIES
github-pages
jekyll-seo-tag
webrick
BUNDLED WITH
2.5.9

View File

@ -1,28 +0,0 @@
Copyright (c) 2002-2009 Jeremiah Fincher and others
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the author of this software nor the name of
contributors to this software may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Portions of the included source code are copyright by its original author(s)
and remain subject to its associated license.

View File

@ -1,6 +0,0 @@
include LICENSE.md
include README.md
include Makefile
include .travis.yml
include requirements.txt
include test/*.py

View File

@ -1,42 +0,0 @@
PYTHON=`which python3`
DESTDIR=/
PROJECT=limnoria
all:
@echo "make source - Create source package"
@echo "make install - Install on local system"
@echo "make buildrpm - Generate a rpm package"
@echo "make builddeb_py2 - Generate a deb package for Python 2"
@echo "make builddeb_py3 - Generate a deb package for Python 3"
@echo "make clean - Get rid of scratch and byte files"
test:
PATH=./scripts/:${PATH} PYTHONPATH=. $(PYTHON) ./scripts/supybot-test test --plugins-dir=plugins/
source:
$(PYTHON) setup.py sdist $(COMPILE)
install:
$(PYTHON) setup.py install --root $(DESTDIR) $(COMPILE)
buildrpm:
$(PYTHON) setup.py bdist_rpm
builddeb_py2:
cp debian/control.py2 debian/control
debuild -us -uc
rm debian/control
builddeb_py3:
cp debian/control.py3 debian/control
debuild -us -uc
rm debian/control
clean:
$(PYTHON) setup.py clean
$(MAKE) -f $(CURDIR)/debian/rules clean
rm -rf build/ MANIFEST
find . -name '*.pyc' -delete
rm debian/control
.PHONY: test

View File

@ -1,63 +1,9 @@
Limnoria is a multipurpose Python IRC bot, designed for flexibility and robustness,
while being easy to install, set up, and maintain.
# Mikaela's fork of Limnoria.
It aims to be an adequate replacement for most existing IRC bots.
It includes a very flexible and powerful
[ACL system](https://docs.limnoria.net/use/capabilities.html)
for controlling access to commands,
an equality powerful
[configuration system](https://docs.limnoria.net/use/configuration.html)
to customize your bot,
as well as more than 60 builtin [plugins](https://limnoria.net/plugins.xhtml)
providing around 400 actual commands.
There are mainly two branches. This one which you are looking at, gh-pages
which is the source of <https://supybot.mikaela.info/>.
There are also dozens of third-party [plugins](https://limnoria.net/plugins.xhtml)
written by dozens of independent developers,
and it is very easy to
[write your own](https://docs.limnoria.net/develop/plugin_tutorial.html)
with only basic knowledge of Python.
It is the successor of
[Supybot](https://sourceforge.net/projects/supybot/)
since 2010 and provides many new features, but keeps full compatibility
with existing configurations and plugins.
# Support
## Documentation
If this is your first install, there is an [install guide](https://docs.limnoria.net/en/latest/use/install.html).
You will probably be pointed to it if you ask on IRC how to install
Limnoria.
TL;DR version:
```
sudo apt-get install python3 python3-pip python3-wheel
pip3 install --user limnoria
# You might need to add $HOME/.local/bin to your PATH
supybot-wizard
```
There is extensive documentation at [docs.limnoria.net] and at
[Gribble wiki]. We took the time to write it; you should take the time to
read it.
[docs.limnoria.net]:https://docs.limnoria.net/
[Gribble wiki]:https://sourceforge.net/p/gribble/wiki/Main_Page/
## IRC channels
### In English
If you have any trouble, feel free to swing by [#limnoria](ircs://irc.libera.chat:6697/#limnoria) on
[Libera.Chat](https://libera.chat/) and ask questions. We'll be happy to help
wherever we can. And by all means, if you find anything hard to
understand or think you know of a better way to do something,
*please* post it on the [issue tracker] so we can improve the bot!
[issue tracker]:https://github.com/ProgVal/Limnoria/issues
### In Other languages
Only in French at the moment, located at [#limnoria-fr on Libera.Chat](ircs://irc.libera.chat:6697/#libera-fr).
**testing** which will be synced with [ProgVal/Limnoria] when needed. It
is used as base for my changes which will be pull requested.
[ProgVal/Limnoria]: https://github.com/ProgVal/Limnoria.git

435
RELNOTES
View File

@ -1,435 +0,0 @@
Version 0.83.5
The minimum supported Python version has been bumped to 2.6.
utils.str.perlVariableSubstitute is deprecated in favor of using Python's
string.Template directly. perlVariableSubstitute will be removed in a future
release.
Factoids' config variable supybot.plugins.Factoids.factoidPrefix has been
replaced by supybot.plugins.Factoids.format, which allows the user to
determine exactly how replies to Factoid queries are formatted.
supybot-botchk no longer runs supybot inside an instance of /bin/sh.
Version 0.83.4.1
Simple bug-fix release for a couple changes that were introduced last minute
before the previous release.
No incompatibilities.
Version 0.83.4
This release contains fixes for Python2.6 compability as well as a re-written
Google plugin which uses the AJAX API. The re-written plugin gained a
translate command and no longer needs an API key.
ChannelLogger has a new config variable, supybot.plugins.ChannelLogger.enable,
which can be used on a per-channel basis to determine whether that channel is
logged.
The RSS announce command has been restructured into the commands "announce
list", "announce remove", and "announce add" in order to simplify the
command's use.
The supybot.directories.plugins config variable now determines its global
directory dynamically instead of adding the directory to the value. This
means values like '/usr/lib/python2.5/site-packages/supybot/plugins' can be
removed from the variable. This should help ease transitioning a Supybot
config from one Python release to another.
Incompatibilities:
supybot.plugins.Google.safeSearch has been renamed to
supybot.plugins.Google.searchFilter
supybot.plugins.Channel.banmask has been removed in favor of a new
supybot.protocols.irc.banmask config variable. This general config variable
is used by the various commands which would need to know what style of banmask
to use.
Version 0.83.3
Overdue bug fix and Python2.5-compatible release. No significant changes to
worry about from the user perspective.
Version 0.83.2
Mainly bug fix release. The most noticeable change being a value of
'default' for supybot.drivers.module will use Socket instead of Twisted.
Version 0.83.1
No incompatibilities, just fixing an important bug with plugin loading.
Version 0.83.0
This far overdue release contains mostly bug-fixes.
Incompatibilities:
Changed the prefixName keyword argument (which appears in various places
in callbacks.py and the reply-related irc methods) to prefixNick.
Version 0.83.0rc3
This release candidate contains mostly bug-fixes.
Incompatibilities:
utils.changeFunctionName was moved to utils.python.changeFunctionName
Version 0.83.0rc2
This release candidate contains a few bug-fixes and some plugins we
forgot in the last RC. Otherwise, everything is compatible.
Version 0.83.0rc1
There have been some fairly significant changes since our last release.
This means that you should uninstall your previous version before
installing this version.
First, plugins are now a directory of files rather than a single file.
This makes it much easier for an individual plugin to supply any
3rd-party modules it may depend on and resolves some bugs we had with
reloading plugins. supybot-plugin-create (nee supybot-newplugin) has
been updated to reflect this. A side effect of using a directory-based
plugin is that @load/@reload are now case-sensitive. "@load foo" is not
the same as "@load Foo".
As part of the conversion to the new plugin format, some plugins were
broken up into more focused plugins. Also, not all of the plugins that
we used to ship are part of this release. Some we moved to the
supybot-plugins package and some others (which would be candidates for
supybot-plugins) have yet to be converted to the new format.
Second, we've updated the scripts that ship with Supybot. As noted in
the previous section, supybot-newplugin is now named
supybot-plugin-create. We've also added the following scripts:
supybot-botchk - Handy script for starting the bot and keeping it
running. Ideal for having cron automatically start the
bot.
supybot-plugin-doc - Generates documentation for the specified
plugin(s). Currently, the documentation is
generated using Structured TeXt so that it can
easily be uploaded to our website.
supybot-plugin-package - The beginning of a script to make a plugin
package which can be uploaded to our website
for general consumption.
supybot-test - Runs a plugin's test suite.
Third, we've broken supybot.utils into focused sub-modules. There's no
longer a supybot.fix module and we now have the following modules:
supybot.utils.file - utilities for dealing with files (e.g. the old
supybot.utils.transactionalFile is now
supybot.utils.file.AtomicFile)
supybot.utils.iter - utilities for dealing with iterables (all, any,
partition, groupBy, choice, etc)
supybot.utils.gen - general purpose utilities which are imported into
the supybot.utils namespace
supybot.utils.net - utilities for dealing with the network
supybot.utils.python - utilities for dealing with Python
supybot.utils.seq - utilities for dealing with sequences
supybot.utils.str - utilities for dealing with strings (including our
new format() function)
supybot.utils.structures - general purpose structures used in Supybot
supybot.utils.web - utilities for dealing with the web (used to be
supybot.webutils)
Fourth, we've added source-nested plugins (using the class
callbacks.Commands). This allows you to group similar commands
together. Some examples are:
Channel.{ban add,ban list,ban remove}
User.{hostmask add,hostmask list,hostmask remove}
Fifth, we've removed the privmsgs module. All of the functionality
that was offered in that module is now available by using commands.wrap.
Use of this is documented at:
http://supybot.com/documentation/help/tutorial/wrap
Sixth, we've renamed some plugin-related API changes. Some classes had
their names changed. The old names are still available for
backwards-compatibility.
callbacks.Privmsg -> callbacks.Plugin
callbacks.PrivmsgCommandAndRegexp -> callbacks.PluginRegexp
callbacks.IrcObjectProxy -> callbacks.NestedCommandsIrcProxy
callbacks.PrivmsgRegexp was removed since its functionality is covered
by setting using PluginRegexp.
Also, the prototype for a plugin's __init__ method changed:
def __init__(self): -> def __init__(self, irc):
Remember to pass the irc object on when you call the parent class's
__init__ method.
Version 0.80.0
We *finally* hit 0.80.0! This release is completely compatible with
the last release candidate.
An update to Babelfish may cause an error message to be displayed in
the console when the bot is first run. The error message should be
gone when the bot is restarted.
We also have a new community website at http://www.supybot.com/ where
our users can submit their own plugins, view/download other people's
plugins and discuss all things Supybot-related.
Version 0.80.0rc3
Another bugfix release. This one was pretty important as it actually
makes supybot.database.plugins.channelSpecific work properly.
Version 0.80.0rc2
supybot.databases.plugins.channelSpecific.channel was renamed to
supybot.databases.plugins.channelSpecific.link.
supybot.databases.plugins.channelSpecific.link.allow was added, which
determines whether a channel will allow other channels to link to its
database.
Infobot is no longer deprecated and the following changes were made to
its config variables:
supybot.plugins.Infobot.answerUnaddressedQuestions was renamed to
supybot.plugins.Infobot.unaddressed.answerQuestions.
supybot.plugins.Infobot.snarfUnaddressedDefinitions was renamed to
supybot.plugins.Infobot.unaddressed.snarfDefinitions.
supybot.plugins.Infobot.unaddressed.replyExistingFactoid was added to
determine whether the bot will reply when someone attempts to create a
duplicate factoid.
Version 0.80.0pre6
Another bugfix release. No incompatibilities known. The only
registry change is that supybot.databases.users.hash has been
removed.
Version 0.80.0pre5
Completely bugfix release. No incompatibilies known.
Version 0.80.0pre4
Mainly a bug fix release. This will likely be the last release before
0.80.0final, but we're gonna let it stew for a couple weeks to attempt
to catch any lingering bugs.
ansycoreDrivers is now deprecated in favor of socketDrivers or
twistedDrivers.
supybot.databases.plugins.channelSpecific.channel is now a channelValue
so that you can link specific channels together (instead of all channels
being linked together).
For those of you that use eval and/or exec, they have been removed from
the Owner plugin and are now in sandbox/Debug.py (which you'll have to
grab from CVS).
Version 0.80.0pre3
The database format for the Note plugin has changed to a flatfile
format; use tools/noteConvert.py to convert it to the new format.
Ditto that for the URL database.
FunDB is deprecated and will be removed at the next major release;
use tools/fundbConvert.py to convert your old FunDB databases to Lart
and Praise databases.
If you had turned off supybot.databases.plugins.channelSpecific, your
non-channel-specific database files had gone directly into your data/
directory. We had some problems with poor interactions between that
configuration variable and channel capabilities, though, so we
changed the implementation so that non-channel-specific databases are
considered databases of a single (configurable) channel (defaulting
to "#"). This will also help others who are converting from
channel-specific to non-channel-specific databases, but for you
who've already made the switch, you'll need to move your database
files again, from data/ to data/# (or whatever channel you might
change that variable to).
supybot.channels doesn't exist anymore; now the only list of channels
to join is per-network, in supybot.networks.<network>.channels.
We weren't serializing supybot.replies.* properly in older versions.
Now we are, but the old, improperly serialized versions won't work
properly. Remove from your configuration file all variables
beginning with "supybot.replies" before you start the bot.
The URL database has been changed again, but it will use a different
filename so you shouldn't run into conflicts, just a newly-empty
database.
We upgraded the SOAP stuff in others; you may do well to do a
setup.py install --clean this time around.
Version 0.80.0pre2
Many more bugs have been fixed. A few more plugins have been updated
to use our new-style database abstraction. If it seems like your
databases are suddenly empty, look for a new database file named
Plugin.dbtype.db. We've also added a few more configuration variables.
Version 0.80.0pre1
Tons of bugs fixed, many features and plugins added. Everything
should be entirely compatible; many more configuration variables have
been added.
Version 0.79.9999
Some more bugs fixed, added a few features and a couple configuration
variabless. This should hopefully be the last release before 0.80.0,
which will finally bring us to pure Beta status.
Version 0.79.999
Some bugs fixed, but the ones that were fixed were pretty big. This
is, of course, completely compatible with the last release.
Version 0.79.99
Many bugs fixed, thanks to the users who reported them. We're
getting asymptotically closer to 0.80.0 -- maybe this'll be the last
one, maybe we'll have to release an 0.79.999 -- either way, we're
getting close :) Check out the ChangeLog for the fixes and a few new
features.
Version 0.79.9
We've changed so much stuff in this release that we've given up on
users upgrading their configuration files for the new release. So
do a clean install (python2.3 setup.py install --clean), run the
wizard again, and kick some butt.
(It's rumored that you can save most of your old configuration by
appending your new configuration at the end of your old configuration
and running supybot with that new configuration file. This, of
course, comes with no warranty or guarantee of utility -- try it if
you want, but backup your original configuration file!)
Version 0.77.2
This is a drop-in replacement for 0.77.1, with two exceptions. The
configuration variable formerly known as
"supybot.plugins.Services.password" is now known as
"supybot.plugins.Services.NickServ.password", due to the fact that
there might be different passwords for NickServ and ChanServ (and
ChanServ passwords are per-channel, whereas NickServ passwords are
global). If you're using the Services plugin, you'll need to make
this change in order to continue identifying with services. The
configuration variable formerly known as
"supybot.plugins.Babelfish.disabledLanguages" is now known as
"supybot.plugins.Babelfish.languages". The configuration variable now
accepts the languages that *will* be translated as opposed to ones
that are *not* translated.
Tests and the developer sandbox are not longer delivered with our
release tarballs. If you're a developer and you want these, you
should either check out CVS or download one of our weekly CVS
snapshots, available at http://supybot.sourceforge.net/snapshots/ .
Version 0.77.1
This is a drop-in replacement for 0.77.0 -- no incompatibilities, to
out knowledge. Simply install over your old installation and restart
your bot :)
Version 0.77.0
Setup.py will automatically remove your old installations for you, no
need to worry about that yourself.
Configuration has been *entirely* redone. Read the new
GETTING_STARTED document to see how to work with configuration
variables now. Your old botscripts from earlier versions *will not*
work with the new configuration method. We'd appreciate it if you'd
rerun the wizard in order for us to find any bugs that remain in it
before we officially declare ourselves Beta. Note also that because
of the new configuration method, the interface for plugins' configure
function has changed: there are no longer any onStart or afterConnect
arguments, so all configuration should be performed via the registry.
Channel capabilities have been changed; rather than being
#channel.capability, they're now #channel,capability. It's a bit
uglier, we know, but dots can be valid in channel names, and we
needed the dot for handling plugin.command capabilities.
tools/ircdbConvert.py should update this for you.
The on-disk format of the user/channel databases has changed to be far
more readable. A conversion utility is included, as mentioned before:
tools/ircdbConvert.py. Run this with no arguments to see the
directions for using it.
Uh, we were just kidding about the upgrade script in 0.76.0 :) It'll
be a little while longer. We do have several little upgrade scripts,
though.
Version 0.76.1
Almost entirely bugfixes, just some minor (and some less minor) bugs
that need to get in before we really start hacking on the next
version. Should be *entirely* compatible with 0.76.0.
Version 0.76.0
Major bugfix release. A great number of bugs fixed. This is the last
release without an upgrade script.
The only hiccup in the upgrade from 0.75.0 should be that you'll need
to update your botscript to reflect the removal of the debug module.
We'd rather you use supybot-wizard to generate a new botscript, of
course, but if you insist on modifying your existing botscript, take a
look at
<http://cvs.sourceforge.net/viewcvs.py/supybot/supybot/src/template.py?r1=1.20&r2=1.21>
to see what you need to do.
Version 0.75.0
Don't forget to reinstall (i.e., run "python setup.py install" as
root). Sometimes it even does good to remove the old installation;
$PYTHON/site-packages/supybot can be removed with no problems
whatsoever.
You will need to re-run supybot-wizard and generate a new botscript.
The Infobot plugin has been removed from this release; it's not ready
for prime time. If you're interested in getting it running (i.e., you
want full Infobot compatibility and aren't satisfied with either
MoobotFactoids or Factoids) then swing over to #supybot and we can
discuss the tests. We simply don't know enough about Infobot to make
sure our Infobot plugin is an exact replica, and need someone's help
with making the changes necessary for that.

70
Relaybot.markdown Normal file
View File

@ -0,0 +1,70 @@
---
layout: page
title: Ignoring RelayBot
permalink: /Relaybot.html
---
RelayBot is the bot which relays between #supybot,#limnoria at a couple of
networks (TODO/FIXME, which ones?). It
is currently using the [LinkRelay](https://github.com/ProgVal/Supybot-plugins/tree/master/LinkRelay)
plugin to do this.
It's sometimes considered as annoyance as it has lately mostly spammed
with join (part messages aren't working, because of a bug (2014-06-23))
messages of people who usually say nothing and this is why this page is
here to tell how to ignore it on various client.
We(who? I?) encourage you to ignore only notices from RelayBot instead of
everything as there are people whom should be heard at OFTC (mainly main
Supybot developer). (TODO/FIXME: is this the case in 2021?)
Related links:
- [LinkRelay plugin](https://github.com/ProgVal/Supybot-plugins/tree/master/LinkRelay)
- [Feature request for smart filtering of joins/quits/parts](https://github.com/ProgVal/Supybot-plugins/issues/66)
- [Feature request for RELAYMSG for more native look&feel](https://github.com/ProgVal/Supybot-plugins/issues/338)
Hostmask of RelayBot on Libera.Chat 2021-06-06:
- `RelayBot!~limnoria@helium.progval.net`
- This is absolute hostmask, also known as NUH (`nick!user@host`)
- `RelayBot*!*@helium.progval.net`
- This is recommended hostmask as it matches RelayBot even if it
cannot use it's primary nickname or networks cannot connect to it's
identd.
## HexChat
From the "Window" menu you can find "Ignore list". Click "Add" and add
one of the hostmasks mentioned above (the lower is recommended).
Uncheck the other checkboxes than "Notice" and you can close the window
and you won't see spamming.
## KVIRC
I am not primarily KVIRC user and I cannot say anything else than right
click RelayBot and select something that matches only RelayBot.
**WARNING: KVIRC makes it very easy to also ignore pinkieval which you
don't want to do as they are author of Limnoria and help people often!**
## Linkinus
According to another person, there is a GUI where you can easily ignore
notices from specific hostmask.
## WeeChat
`/filter add relaybotnotices * irc_notice+nick_RelayBot *`
This creates a new filter with the name "relaybotnotices" which filters
all notices from the nickname "RelayBot".
---
This page is very likely missing many IRC clients. Could you
[open an issue](https://github.com/mikaela/limnoria/issues)
about how to do this with your IRC client that isn't mentioned here?
---

141
Supybot.markdown Normal file
View File

@ -0,0 +1,141 @@
---
layout: page
title: Security issues
permalink: /Supybot.html
---
Supybot git repository was declared dead on 2018-05-10 and archived
on GitHub. [v0.84.0 was the last release at that time](https://github.com/Supybot/Supybot/releases/tag/v0.84.0).
0.83.4.1 used to be a very common release available through several Linux
distributions for years and thus I made this page, which I guess is now
available more of for historical reasons.
**_WARNING: most of the content originates from 2014!_**
## The issues of 0.83.4.1.
### 1. Anyone can crash it and computer where it's running on
And this is very easy. Just run the command
`!misc last --regexp m/(.*\w){512}/`
where ! is the prefix character.
Misc is loaded by default and cannot be unloaded without modifying the
config.
- [Limnoria issue #157](https://github.com/ProgVal/Limnoria/issues/157)
- Fixing commits: [3526d5d](https://github.com/ProgVal/Limnoria/commit/3526d5dabf587457a43af8bee8d4db21986e8222) & [e11dc28](https://github.com/ProgVal/Limnoria/commit/e11dc28025de877b1b6cf059013eef88337b7e44)
- [Ubuntu bug #996947](https://bugs.launchpad.net/ubuntu/+source/supybot/+bug/996947)
- [Debian bug #672214](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=672214)
### 2. The previous wasn't the only way to do this
Everyone can also make the bot count an equation, which brings it and the
host computer down.
For example:
`!math calc factorial(999999)`
This requires Math plugin which comes with Supybot, but isn't load by
default.
- [Limnoria issue #354](https://github.com/ProgVal/Limnoria/issues/354)
- Fixing commit: [695078e](https://github.com/ProgVal/Limnoria/commit/695078edeb91e5ff1eec728fedf0e0c27b55c505)
- [Ubuntu bug #996950](https://bugs.launchpad.net/ubuntu/+source/supybot/+bug/996950)
- [Debian bug 672215](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=672215)
### 3. Anyone can access network services via the bot.
I don't have example command for this, but it happens by nesting
"format cut" and "misc tell".
What does this mean? Anyone can tell the bot to ghost someone else on same
account, take over a channel by telling the bot to give flags
(if it has correct flags), change password of the account and everything
else what you do with network services.
- _This was only reported at IRC and I am unable to find issue report
or fixing commit. ~~Mikaela on 2015-01-04._
### 4. Web page with special characters in \<title\> can be used to send DCC/CTCP commands.
This doesn't mean only things like CTCP actions (also known as /me),
but known problems with old routers
( `FF ? DCC SEND “ff???f??????????????” 0 0 0` ) which make them reconnect
to the internet.
Usage:
- `!web title <malicious.page.here>`
- `!web fetch <malicious.page.here>`
_This was only reported at IRC and I am unable to find issue report
or fixing commit. ~~Mikaela on 2015-01-04._
### 5. Web Titlte/Fetch can be used for DoS
They are vulnerable to queries to servers which have custom headers
which can lead to DoS.
_This was only reported at IRC and I am unable to find issue report
or fixing commit. ~~Mikaela on 2015-01-04._
### 6. QuoteGrabs grab command also works in PM
and can grab private content such as `user register` or `user identify` or
with the case of owner possibly NickServ passwords and others not so nice
things.
- _It appears this issue was only reported at IRC._
- Fixing commit: [a3346343679f3bdf8c77d9efb5a2097e215d51df](https://github.com/ProgVal/Limnoria/commit/a3346343679f3bdf8c77d9efb5a2097e215d51df)
### Are these issues publicly known?
**Of course they are.** Issue reports are below the actual issues.
The first issue has been also used to take down some of
[Ubuntu IRC bots](https://wiki.ubuntu.com/IRC/Bots) several times.
At least UbotX (I don't remember the number) and meetingology.
Some of these issues are fixed in git repository, but most people aren't
using it. If you wish to start using it, please scroll down to
installation instructions lower this page even though [Limnoria] and
[gribble] are more recommended.
### How to avoid them?
You can add anticapability for these commands using
`owner defaultcapability`, but that is only a temporary solution.
There can also be other issues.
There are also two active Supybot forks, known as [Limnoria] and
[Gribble], which are actively developed and have fixed these issues.
If you want permanent solution, you should install either of them.
## Possibly interesting links
- [Comparsion of commit activity between Limnoria, Gribble and Supybot](https://www.openhub.net/p/compare?project_0=Limnoria&project_1=Gribble%3A+Support+Bottie&project_2=Supybot).
- [Gribble's modifications to stock Supybot](https://sourceforge.net/p/gribble/wiki/Gribble_Project_Git_Repository/)
- [Limnoria's modifications to Gribble.](https://github.com/ProgVal/Limnoria/wiki/LGC)
- Features of Gribble are fully merged to Limnoria.
Your current botname.conf is **100% compatible with forks**.
[Join Supybot channels on LiberaChat!](ircs://irc.libera.chat:6697/#supybot,#gribble,#limnoria)
[Limnoria]: https://github.com/ProgVal/Limnoria
[Gribble]: http://github.com/nanotube/supybot_fixes
## Installing forks
_This section has been removed in order to not duplicate
[Limnoria's documentation.](http://doc.supybot.aperio.fr/en/latest/use/install.html)_
---
Do you know issue that isn't mentioned here? If it's not already reported,
please report it on [Limnoria's issue tracker.](https://github.com/ProgVal/Limnoria/issues)
If it's known, but just not reported here, [please feel free to add it.](https://github.com/Mikaela/limnoria/edit/gh-pages/Supybot.markdown)

36
_config.yml Normal file
View File

@ -0,0 +1,36 @@
theme: minima
title: Mikaela's Supybot site
tagline: Things official documentation may not tell you
author:
name: "Aminda Suomalainen"
url: "https://aminda.eu/"
description: > # this means to ignore newlines until "baseurl:"
Mikaela's Supybot site where nowadays the only content is security issues
of stock Supybot.
baseurl: "" # the subpath of your site, e.g. /blog/
url: "https://supybot.mikaela.info/" # the base hostname & protocol for your site
github_username: Mikaela
lang: en
timezone: Etc/UTC
encoding: utf-8
plugins:
# - jekyll-mentions
- jekyll-redirect-from
- jekyll-sitemap
- jekyll-seo-tag
sitemap:
file: "/sitemap.xml"
include: [robots.txt]
robots: nofollow, noai
icon: https://github.com/ProgVal/Supybot-website/raw/master/static/logo.png
markdown: kramdown
kramdown:
parse_block_html: true
#webmaster_verifications:
#google:
#bing:
defaults:
- scope:
path: "*"
values:
image: https://github.com/ProgVal/Supybot-website/raw/master/static/logo.png

32
_includes/footer.html Normal file
View File

@ -0,0 +1,32 @@
<footer class="site-footer h-card">
<data class="u-url" href="{{ "/" | relative_url }}"></data>
<div class="wrapper">
<h2 class="footer-heading">{{ site.title | escape }}</h2>
<div class="footer-col-wrapper">
<div class="footer-col footer-col-1">
<ul class="contact-list">
<li class="p-name">
<a rel="me prefetch" href="{{ site.author.url }}">{{ site.author.name }}</a><br>
{{ site.title | escape }}
</li>
{%- if site.email -%}
<li><a class="u-email" href="mailto:{{ site.email }}">{{ site.email }}</a></li>
{%- endif -%}
</ul>
</div>
<div class="footer-col footer-col-2">
{%- include social.html -%}
</div>
<div class="footer-col footer-col-3">
<p>{{- site.description | escape -}}</p>
</div>
</div>
</div>
</footer>

12
_includes/head.html Normal file
View File

@ -0,0 +1,12 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!---->
{%- seo -%}
<!---->
<meta name="robots" content="{% if page.robots %}{{ page.robots }} {% else %}{{ site.robots }} {% endif %}">
<link rel="icon" href="https://github.com/ProgVal/Supybot-website/raw/master/static/logo.png">
<link rel="stylesheet" href="{{ "/assets/main.css" | prepend: site.baseurl }}">
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}">
</head>

210
_sass/_base.scss Normal file
View File

@ -0,0 +1,210 @@
:root {
color-scheme: dark light;
}
/**
* Reset some basic elements
*/
body, h1, h2, h3, h4, h5, h6,
p, blockquote, pre, hr,
dl, dd, ol, ul, figure {
margin: 0;
padding: 0;
}
/**
* Basic styling
*/
body {
font-family: $base-font-family;
font-size: $base-font-size;
line-height: $base-line-height;
font-weight: 300;
color: $text-color;
background-color: $background-color;
-webkit-text-size-adjust: 100%;
}
/**
* Set `margin-bottom` to maintain vertical rhythm
*/
h1, h2, h3, h4, h5, h6,
p, blockquote, pre,
ul, ol, dl, figure,
%vertical-rhythm {
margin-bottom: $spacing-unit / 2;
}
/**
* Images
*/
img {
max-width: 100%;
vertical-align: middle;
}
/**
* Figures
*/
figure > img {
display: block;
}
figcaption {
font-size: $small-font-size;
}
/**
* Lists
*/
ul, ol {
margin-left: $spacing-unit;
}
li {
> ul,
> ol {
margin-bottom: 0;
}
}
/**
* Headings
*/
h1, h2, h3, h4, h5, h6 {
font-weight: 300;
}
/**
* Links
*/
a {
color: $brand-color;
//text-decoration: none;
text-decoration: underline;
&:visited {
//color: darken($brand-color, 15%);
}
&:hover {
color: $text-color;
//text-decoration: underline;
}
}
/**
* Blockquotes
*/
blockquote {
color: $grey-color;
border-left: 4px solid $grey-color-light;
padding-left: $spacing-unit / 2;
font-size: 18px;
letter-spacing: -1px;
font-style: italic;
> :last-child {
margin-bottom: 0;
}
}
/**
* Code formatting
*/
pre,
code {
font-family: $monospace-font-family;
font-size: 15px;
border: 1px solid; //$grey-color-light;
border-radius: 3px;
background-color: revert; //#eef;
}
code {
padding: 1px 5px;
}
pre {
padding: 8px 12px;
overflow-x: scroll;
> code {
border: 0;
padding-right: 0;
padding-left: 0;
}
}
/**
* Wrapper
*/
.wrapper {
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
margin-right: auto;
margin-left: auto;
padding-right: $spacing-unit;
padding-left: $spacing-unit;
@extend %clearfix;
@include media-query($on-laptop) {
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
max-width: calc(#{$content-width} - (#{$spacing-unit}));
padding-right: $spacing-unit / 2;
padding-left: $spacing-unit / 2;
}
}
/**
* Clearfix
*/
%clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
/**
* Icons
*/
.icon {
> svg {
display: inline-block;
width: 16px;
height: 16px;
vertical-align: middle;
path {
fill: $grey-color;
}
}
}

236
_sass/_layout.scss Normal file
View File

@ -0,0 +1,236 @@
/**
* Site header
*/
.site-header {
border-top: 5px solid $grey-color-dark;
border-bottom: 1px solid $grey-color-light;
min-height: 56px;
// Positioning context for the mobile navigation icon
position: relative;
}
.site-title {
font-size: 26px;
line-height: 56px;
letter-spacing: -1px;
margin-bottom: 0;
float: left;
&,
&:visited {
color: $grey-color-dark;
}
}
.site-nav {
float: right;
line-height: 56px;
.menu-icon {
display: none;
}
.page-link {
color: $text-color;
line-height: $base-line-height;
// Gaps between nav items, but not on the first one
&:not(:first-child) {
margin-left: 20px;
}
}
@include media-query($on-palm) {
position: absolute;
top: 9px;
right: 30px;
background-color: $background-color;
border: 1px solid $grey-color-light;
border-radius: 5px;
text-align: right;
.menu-icon {
display: block;
float: right;
width: 36px;
height: 26px;
line-height: 0;
padding-top: 10px;
text-align: center;
> svg {
width: 18px;
height: 15px;
path {
fill: $grey-color-dark;
}
}
}
.trigger {
clear: both;
display: none;
}
&:hover .trigger {
display: block;
padding-bottom: 5px;
}
.page-link {
display: block;
padding: 5px 10px;
}
}
}
/**
* Site footer
*/
.site-footer {
border-top: 1px solid $grey-color-light;
padding: $spacing-unit 0;
}
.footer-heading {
font-size: 18px;
margin-bottom: $spacing-unit / 2;
}
.contact-list,
.social-media-list {
list-style: none;
margin-left: 0;
}
.footer-col-wrapper {
font-size: 15px;
color: $grey-color;
margin-left: -$spacing-unit / 2;
@extend %clearfix;
}
.footer-col {
float: left;
margin-bottom: $spacing-unit / 2;
padding-left: $spacing-unit / 2;
}
.footer-col-1 {
width: -webkit-calc(35% - (#{$spacing-unit} / 2));
width: calc(35% - (#{$spacing-unit} / 2));
}
.footer-col-2 {
width: -webkit-calc(20% - (#{$spacing-unit} / 2));
width: calc(20% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(45% - (#{$spacing-unit} / 2));
width: calc(45% - (#{$spacing-unit} / 2));
}
@include media-query($on-laptop) {
.footer-col-1,
.footer-col-2 {
width: -webkit-calc(50% - (#{$spacing-unit} / 2));
width: calc(50% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
@include media-query($on-palm) {
.footer-col {
float: none;
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
/**
* Page content
*/
.page-content {
padding: $spacing-unit 0;
}
.page-heading {
font-size: 20px;
}
.post-list {
margin-left: 0;
list-style: none;
> li {
margin-bottom: $spacing-unit;
}
}
.post-meta {
font-size: $small-font-size;
color: $grey-color;
}
.post-link {
display: block;
font-size: 24px;
}
/**
* Posts
*/
.post-header {
margin-bottom: $spacing-unit;
}
.post-title {
font-size: 42px;
letter-spacing: -1px;
line-height: 1;
@include media-query($on-laptop) {
font-size: 36px;
}
}
.post-content {
margin-bottom: $spacing-unit;
h2 {
font-size: 32px;
@include media-query($on-laptop) {
font-size: 28px;
}
}
h3 {
font-size: 26px;
@include media-query($on-laptop) {
font-size: 22px;
}
}
h4 {
font-size: 20px;
@include media-query($on-laptop) {
font-size: 18px;
}
}
}

View File

@ -0,0 +1,67 @@
/**
* Syntax highlighting styles
*/
.highlight {
background: #fff;
@extend %vertical-rhythm;
.c { color: #998; font-style: italic } // Comment
.err { color: #a61717; background-color: #e3d2d2 } // Error
.k { font-weight: bold } // Keyword
.o { font-weight: bold } // Operator
.cm { color: #998; font-style: italic } // Comment.Multiline
.cp { color: #999; font-weight: bold } // Comment.Preproc
.c1 { color: #998; font-style: italic } // Comment.Single
.cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
.gd { color: #000; background-color: #fdd } // Generic.Deleted
.gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
.ge { font-style: italic } // Generic.Emph
.gr { color: #a00 } // Generic.Error
.gh { color: #999 } // Generic.Heading
.gi { color: #000; background-color: #dfd } // Generic.Inserted
.gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
.go { color: #888 } // Generic.Output
.gp { color: #555 } // Generic.Prompt
.gs { font-weight: bold } // Generic.Strong
.gu { color: #aaa } // Generic.Subheading
.gt { color: #a00 } // Generic.Traceback
.kc { font-weight: bold } // Keyword.Constant
.kd { font-weight: bold } // Keyword.Declaration
.kp { font-weight: bold } // Keyword.Pseudo
.kr { font-weight: bold } // Keyword.Reserved
.kt { color: #458; font-weight: bold } // Keyword.Type
.m { color: #099 } // Literal.Number
.s { color: #d14 } // Literal.String
.na { color: #008080 } // Name.Attribute
.nb { color: #0086B3 } // Name.Builtin
.nc { color: #458; font-weight: bold } // Name.Class
.no { color: #008080 } // Name.Constant
.ni { color: #800080 } // Name.Entity
.ne { color: #900; font-weight: bold } // Name.Exception
.nf { color: #900; font-weight: bold } // Name.Function
.nn { color: #555 } // Name.Namespace
.nt { color: #000080 } // Name.Tag
.nv { color: #008080 } // Name.Variable
.ow { font-weight: bold } // Operator.Word
.w { color: #bbb } // Text.Whitespace
.mf { color: #099 } // Literal.Number.Float
.mh { color: #099 } // Literal.Number.Hex
.mi { color: #099 } // Literal.Number.Integer
.mo { color: #099 } // Literal.Number.Oct
.sb { color: #d14 } // Literal.String.Backtick
.sc { color: #d14 } // Literal.String.Char
.sd { color: #d14 } // Literal.String.Doc
.s2 { color: #d14 } // Literal.String.Double
.se { color: #d14 } // Literal.String.Escape
.sh { color: #d14 } // Literal.String.Heredoc
.si { color: #d14 } // Literal.String.Interpol
.sx { color: #d14 } // Literal.String.Other
.sr { color: #009926 } // Literal.String.Regex
.s1 { color: #d14 } // Literal.String.Single
.ss { color: #990073 } // Literal.String.Symbol
.bp { color: #999 } // Name.Builtin.Pseudo
.vc { color: #008080 } // Name.Variable.Class
.vg { color: #008080 } // Name.Variable.Global
.vi { color: #008080 } // Name.Variable.Instance
.il { color: #099 } // Literal.Number.Integer.Long
}

68
assets/main.scss Normal file
View File

@ -0,0 +1,68 @@
---
# front-matter
---
@charset "utf-8";
$base-font-family: ui-sans-serif, system-ui, "Liberation Sans", Arimo, Arial,
sans-serif;
$monospace-font-family: ui-monospace, "Liberation Mono", Cousine, "Courier New",
monospace;
@import "{{ site.theme }}";
:root {
color-scheme: dark light !important;
}
* {
// box-sizing: border-box !important;
color: revert !important;
background-color: revert !important;
//margin: auto !important;
// line-height: 1.2 !important;
font-size: revert;
//padding: auto !important;
overflow-wrap: break-word !important;
hyphens: auto !important;
}
a {
text-decoration: underline !important;
}
pre,
code {
font-size: 0.8em !important;
}
img {
border-radius: 50% !important;
display: block;
margin-left: auto !important;
margin-right: auto !important;
@media (min-width: 395px) {
display: float !important;
float: right !important;
}
}
// Customize the dark theme to be more me
@media (prefers-color-scheme: dark) {
* {
color: #ffb700 !important;
border-color: #ffb700 !important;
background-color: #000000 !important;
}
.site-nav {
color-scheme: only dark !important;
color: #ffb700 !important;
background-color: #000000 !important;
color: #ffb700 !important;
}
// I don't want links to be restored to amber'
a {
color: revert !important;
}
}

30
feed.xml Normal file
View File

@ -0,0 +1,30 @@
---
layout: null
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ site.title | xml_escape }}</title>
<description>{{ site.description | xml_escape }}</description>
<link>{{ site.url }}{{ site.baseurl }}/</link>
<atom:link href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml"/>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
<generator>Jekyll v{{ jekyll.version }}</generator>
{% for post in site.posts limit:10 %}
<item>
<title>{{ post.title | xml_escape }}</title>
<description>{{ post.content | xml_escape }}</description>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
<link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>
<guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>
{% for tag in post.tags %}
<category>{{ tag | xml_escape }}</category>
{% endfor %}
{% for cat in post.categories %}
<category>{{ cat | xml_escape }}</category>
{% endfor %}
</item>
{% endfor %}
</channel>
</rss>

22
index.markdown Normal file
View File

@ -0,0 +1,22 @@
---
layout: default
---
**_WARNING: most of the content on this site originates from 2014!_**
Welcome to Mikaela's Supybot pages.
This site isn't official and won't help with most of issues. In case you
are looking for the official sites, they are here:
- [Limnoria's website](https://limnoria.net/)
- [Limnoria official documentation](https://docs.limnoria.net/)
- [Supybook](https://hoxu.github.io/supybook/devel/)
- [Gribble Wiki](https://sourceforge.net/p/gribble/wiki/Main_Page/)
I also have [something in my gist repo](https://gitea.blesmrt.net/mikaela/gist/src/branch/master/irc/limnoria/)
at 2021-06-11 16:07 UTC [opinionated titlefetching instructions](https://gitea.blesmrt.net/mikaela/gist/src/branch/master/irc/limnoria/titlefetching.md).
If you cannot find what you are looking for from them, please come to IRC
and ask. The Support channels are
[#supybot,#limnoria on irc.libera.chat](ircs://irc.libera.chat:6697/%23supybot%2c%23limnoria)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,100 +0,0 @@
# -*- encoding: utf8 -*-
###
# Copyright (c) 2010, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
"""
Supybot utility functions localization in French.
"""
def pluralize(s):
"""Returns the plural of s.
"""
lowered = s.lower()
if lowered.endswith('ou') and \
lowered in ['bijou', 'caillou', 'chou', 'genou', 'hibou', 'joujou',
'pou']:
return s + 'x'
elif lowered.endswith('al') and \
lowered not in ['bal', 'carnaval', 'chacal', 'festival', 'récital',
'régal', 'cal', 'étal', 'aval', 'caracal', 'val', 'choral',
'corral', 'galgal', 'gayal']:
return s[0:-2] + 'aux'
elif lowered.endswith('ail') and \
lowered not in ['bail', 'corail', 'émail', 'soupirail', 'travail',
'ventail', 'vitrail', 'aspirail', 'fermail']:
return s[0:-3] + 'aux'
elif lowered.endswith('eau'):
return s + 'x'
elif lowered == 'pare-feu':
return s
elif lowered.endswith('eu') and \
lowered not in ['bleu', 'pneu', 'émeu', 'enfeu']:
# Note: when 'lieu' is a fish, it has a 's' ; else, it has a 'x'
return s + 'x'
else:
return s + 's'
def depluralize(s):
"""Returns the singular of s."""
lowered = s.lower()
if lowered.endswith('aux') and \
lowered in ['baux', 'coraux', 'émaux', 'soupiraux', 'travaux',
'ventaux', 'vitraux', 'aspiraux', 'fermaux']:
return s[0:-3] + 'ail'
elif lowered.endswith('aux'):
return s[0:-3] + 'al'
else:
return s[0:-1]
def ordinal(i):
"""Returns i + the ordinal indicator for the number.
Example: ordinal(3) => '3ème'
"""
i = int(i)
if i == 1:
return '1er'
else:
return '%sème' % i
def be(i):
"""Returns the form of the verb 'être' based on the number i."""
# Note: this function is used only for the third person
if i == 1:
return 'est'
else:
return 'sont'
def has(i):
"""Returns the form of the verb 'avoir' based on the number i."""
# Note: this function is used only for the third person
if i == 1:
return 'a'
else:
return 'ont'

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot-adduser.1
.\"
.TH SUPYBOT-ADDUSER 1 "APRIL 2005"
.SH NAME
supybot-adduser \- Adds a user to a Supybot users.conf file
.SH SYNOPSIS
.B supybot-adduser
.RI [ options ] " users.conf
.SH DESCRIPTION
.B supybot-adduser
adds a user to the specified users.conf file.
.SH OPTIONS
.TP
.B \-\^\-version
Show version of program.
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.BR \-u " NAME" "\fR,\fP \-\^\-username=" NAME
Specifies the username to use for the new user.
.TP
.BR \-p " PASSWORD" "\fR,\fP \-\^\-password=" PASSWORD
Specifies the password to use for the new user.
.TP
.BR \-c " CAPABILITY" "\fR,\fP \-\^\-capability=" CAPABILITY
Capability the user should have; this option may be given
multiple times.
.SH "SEE ALSO"
.IR python (1),
.IR supybot (1),
.IR supybot-test (1),
.IR supybot-botchk (1),
.IR supybot-wizard (1),
.IR supybot-plugin-doc (1),
.IR supybot-plugin-create (1)
.SH AUTHOR
This manual page was originally written by James McCoy
<vega dot james at gmail dot com>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

View File

@ -1,54 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot-botchk.1
.\"
.TH SUPYBOT-BOTCHK 1 "APRIL 2005"
.SH NAME
supybot-botchk \- A script to start Supybot if it's not already running.
.SH SYNOPSIS
.B supybot-botchk
.RI [ options ]
.SH DESCRIPTION
.B supybot-botchk
is a script that will start Supybot if it detects that one is not currently
running. This can be useful for scheduling
.IR supybot (1)
to run via
.IR cron (8).
.SH OPTIONS
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.BR \-v ", " \-\^\-verbose
Use verbose output when running the script.
.TP
.BI \-\^\-botdir= BOTDIR
Determines which directory the bot be started in.
.TP
.BI \-\^\-pidfile= PIDFILE
Specifies the name of the pidfile to look for. This should be relative
to the given botdir.
.TP
.BI \-\^\-supybot= SUPYBOT
Specifies the location of
.IR supybot (1).
If this is not given, it is assumed that
.IR supybot (1)
is in the user's $PATH.
.TP
.BI \-\^\-conffile= CONFFILE
Specifies the path to the bot's configuration file. This will be used
when (re)starting the bot.
.SH "SEE ALSO"
.IR python (1),
.IR supybot (1),
.IR supybot-test (1),
.IR supybot-wizard (1),
.IR supybot-adduser (1),
.IR supybot-plugin-doc (1),
.IR supybot-plugin-create (1)
.SH AUTHOR
This manual page was originally written by James McCoy
<vega dot james at gmail dot com>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

View File

@ -1,43 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot-plugin-create.1
.\"
.TH SUPYBOT-PLUGIN-CREATE 1 "APRIL 2005"
.SH NAME
supybot-plugin-create \- A wizard for creating Supybot plugins
.SH SYNOPSIS
.B supybot-plugin-create
.RI [ options ]
.SH DESCRIPTION
.B supybot-plugin-create
is a wizard that creates a template python source file for a new
.IR supybot (1)
plugin.
.SH OPTIONS
.TP
.B \-\^\-version
Show version of program.
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.BI \-n " NAME" "\fR,\fP \-\^\-name=" NAME
Sets the name for the plugin.
.TP
.BR \-t ", " \-\^\-thread
Makes the plugin threaded.
.TP
.BI \-\^\-real\-name= REALNAME
Specify what real name the copyright is assigned to.
.SH "SEE ALSO"
.IR python (1),
.IR supybot (1),
.IR supybot-test (1),
.IR supybot-botchk (1),
.IR supybot-wizard (1),
.IR supybot-adduser (1),
.IR supybot-plugin-doc (1)
.SH AUTHOR
This manual page was originally written by James McCoy
<vega dot james at gmail dot com>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

View File

@ -1,48 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot-plugin-doc.1
.\"
.TH SUPYBOT-PLUGIN-DOC 1 "May 2009"
.SH NAME
supybot-plugin-doc \- Generates the documentation for a Supybot plugin
.SH SYNOPSIS
.B supybot-plugin-doc
.RI [ options ]
.SH DESCRIPTION
.B supybot-plugin-doc
is used to generate documentation (StructuredText or reStructuredText format)
for a
.IR supybot (1)
plugin.
.SH OPTIONS
.TP
.B \-\^\-version
Show version of program.
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.BR \-c ", " \-\^\-clean
Clean the various data/conf/log directories after generating the docs.
.TP
.BR \-o ", " \-\^\-output\-dir= \fIOUTPUTDIR
Specifies the directory in which to write the documentation for the plugin.
.TP
.BR \-f ", " \-\^\-format= \fIFORMAT
Specifies which output format to use. Choices are 'rst' or 'stx'.
.TP
.BI \-\^\-plugins\-dir= PLUGINSDIRS
Looks in the given directory for plugins and generates documentation for all of
them.
.SH "SEE ALSO"
.IR python (1),
.IR supybot (1),
.IR supybot-test (1),
.IR supybot-botchk (1),
.IR supybot-wizard (1),
.IR supybot-adduser (1),
.IR supybot-plugin-create (1)
.SH AUTHOR
This manual page was originally written by James McCoy
<vega dot james at gmail dot com>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

View File

@ -1,35 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot-reset-password.1
.\"
.TH SUPYBOT-RESET-PASSWORD 1 "JUNE 2022"
.SH NAME
supybot-reset-password \- Changes a user's password in a Supybot users.conf file
.SH SYNOPSIS
.B supybot-reset-password
.RI [ options ] " users.conf
.SH DESCRIPTION
.B supybot-reset-password
changes a user's password in a Supybot users.conf file
.SH OPTIONS
.TP
.B \-\^\-version
Show version of program.
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.BR \-u " NAME" "\fR,\fP \-\^\-username=" NAME
Specifies the username to use for the new user.
.TP
.BR \-p " PASSWORD" "\fR,\fP \-\^\-password=" PASSWORD
Specifies the new password to use for the new user.
.SH "SEE ALSO"
.IR python (1),
.IR supybot (1),
.IR supybot-adduser (1)
.SH AUTHOR
This manual page was originally written by Valentin Lorentz
<progval plus limnoria at progval dot net>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

View File

@ -1,51 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot-test.1
.\"
.TH SUPYBOT-TEST 1 "OCTOBER 2005"
.SH NAME
supybot-test \- Runs the test suite for a Supybot plugin
.SH SYNOPSIS
.B supybot-test
.RI [ options ] " plugins
.SH DESCRIPTION
.B supybot-test
Runs the test suite for a Supybot plugin
.SH OPTIONS
.TP
.B \-\^\-version
Show version of program.
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.BR \-c ", " \-\^\-clean
Cleans the various data/conf/logs directories before running tests.
.TP
.BR \-t " TIMEOUT" "\fR,\fP \-\^\-timeout=" TIMEOUT
Specifies the timeout for tests to return responses.
.TP
.BR \-v ", " \-\^\-verbose
Sets the verbose flag, logging extra information about each test that runs.
.TP
.BR \-\^\-no\-network
Prevents the network-based tests from being run.
.TP
.BR \-\^\-trace
Traces all calls made. Unless you're really in a pinch, you probably
shouldn't do this; it results in copious amounts of output.
.TP
.BR "\fR,\fP \-\^\-plugins\-dir=" PLUGINSDIR
Looks in the given directory for plugins and loads the tests for all of them.
.SH "SEE ALSO"
.IR python (1),
.IR supybot (1),
.IR supybot-botchk (1),
.IR supybot-wizard (1),
.IR supybot-adduser (1),
.IR supybot-plugin-doc (1),
.IR supybot-plugin-create (1)
.SH AUTHOR
This manual page was originally written by James McCoy
<vega dot james at gmail dot com>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

View File

@ -1,42 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot-wizard.1
.\"
.TH SUPYBOT-WIZARD 1 "SEPTEMBER 2004"
.SH NAME
supybot-wizard \- A wizard for creating Supybot configuration files
.SH SYNOPSIS
.B supybot-wizard
.RI [ options ]
.SH DESCRIPTION
.B supybot-wizard
is an in-depth wizard that provides a nice user interface for creating
configuration files for
.IR supybot (1).
.SH OPTIONS
.TP
.B \-\^\-version
Show version of program.
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.B \-\^\-allow\-root
Determines whether the wizard will be allowed to run as root. You do not
want this. Do not do it. Even if you think you want it, you do not.
.TP
.B \-\^\-no\-network
Determines whether the wizard will be allowed to run without a network
connection.
.SH "SEE ALSO"
.IR python (1),
.IR supybot (1),
.IR supybot-test (1),
.IR supybot-botchk (1),
.IR supybot-adduser (1),
.IR supybot-plugin-doc (1),
.IR supybot-plugin-create (1)
.SH AUTHOR
This manual page was originally written by James McCoy
<vega dot james at gmail dot com>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

View File

@ -1,66 +0,0 @@
.\" Process this file with
.\" groff -man -Tascii supybot.1
.\"
.TH SUPYBOT 1 "JULY 2009"
.SH NAME
supybot - A robust and user friendly Python IRC bot
.SH SYNOPSIS
.B supybot
.RI [ options ] " configFile
.SH DESCRIPTION
.B Supybot
is a robust, user-friendly, and programmer-friendly Python IRC bot.
It aims to be an adequate replacement for most existing IRC bots. It
includes a very flexible and powerful ACL system for controlling access
to commands, as well as more than 50 builtin plugins providing around
400 actual commands.
.SH OPTIONS
.TP
.B \-\^\-version
Show version of program.
.TP
.BR \-h ", " \-\^\-help
Show summary of options.
.TP
.BR \-P ", " \-\^\-profile
Enable profiling.
.TP
.BI \-n " NICK" "\fR,\fP \-\^\-nick=" NICK
Nick the bot should use.
.TP
.BI \-u " USER" "\fR,\fP \-\^\-user=" USER
Full username the bot should use.
.TP
.BI \-i " IDENT" "\fR,\fP \-\^\-ident=" IDENT
Ident the bot should use.
.TP
.BR \-d ", " \-\^\-daemon
Determines whether the bot will daemonize. This is a no-op on
non-POSIX systems.
.TP
.B \-\^\-allow\-default\-owner
Determines whether the bot will allow its defaultCapabilities not to
include "\-owner", thus giving all users the owner capability by
default. This is dumb, hence we require a command-line option to
enable it.
.TP
.B \-\^\-allow\-root
Determines whether the bot will be allowed to run as root. You do not
want this. Do not do it. Even if you think you want it, you do not.
.TP
.B \-\^\-debug
Determines whether some extra debugging stuff will be logged by this
script.
.SH "SEE ALSO"
.IR python (1),
.IR supybot-test (1),
.IR supybot-botchk (1),
.IR supybot-wizard (1),
.IR supybot-adduser (1),
.IR supybot-plugin-doc (1),
.IR supybot-plugin-create (1)
.SH AUTHOR
This manual page was originally written by James McCoy
<vega dot james at gmail dot com>. Permission is granted to copy,
distribute and/or modify this document under the terms of the Supybot
license, a BSD-style license.

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"devDependencies": {
"prettier": "3.3.0"
}
}

View File

@ -1,86 +0,0 @@
.. _plugin-Admin:
Documentation for the Admin plugin for Supybot
==============================================
Purpose
-------
These are commands useful for administrating the bot; they all require their
caller to have the 'admin' capability. This plugin is loaded by default.
Usage
-----
This plugin provides access to administrative commands, such as
adding capabilities, managing ignore lists, and joining channels.
This is a core Supybot plugin that should not be removed!
.. _commands-Admin:
Commands
--------
.. _command-admin-acmd:
acmd <command> [<arg> ...]
Perform <command> (with associated <arg>s on all channels on current network.
.. _command-admin-capability.add:
capability add <name|hostmask> <capability>
Gives the user specified by <name> (or the user to whom <hostmask> currently maps) the specified capability <capability>
.. _command-admin-capability.remove:
capability remove <name|hostmask> <capability>
Takes from the user specified by <name> (or the user to whom <hostmask> currently maps) the specified capability <capability>
.. _command-admin-channels:
channels takes no arguments
Returns the channels the bot is on.
.. _command-admin-clearq:
clearq takes no arguments
Clears the current send queue for this network.
.. _command-admin-ignore.add:
ignore add <hostmask|nick> [<expires>]
This will set a persistent ignore on <hostmask> or the hostmask currently associated with <nick>. <expires> is an optional argument specifying when (in "seconds from now") the ignore will expire; if it isn't given, the ignore will never automatically expire.
.. _command-admin-ignore.list:
ignore list takes no arguments
Lists the hostmasks that the bot is ignoring.
.. _command-admin-ignore.remove:
ignore remove <hostmask|nick>
This will remove the persistent ignore on <hostmask> or the hostmask currently associated with <nick>.
.. _command-admin-join:
join <channel> [<key>]
Tell the bot to join the given channel. If <key> is given, it is used when attempting to join the channel.
.. _command-admin-nick:
nick [<nick>] [<network>]
Changes the bot's nick to <nick>. If no nick is given, returns the bot's current nick.
.. _conf-Admin:
Configuration
-------------
.. _conf-supybot.plugins.Admin.public:
supybot.plugins.Admin.public
This config variable defaults to "True", is not network-specific, and is not channel-specific.
Determines whether this plugin is publicly visible.

View File

@ -1,59 +0,0 @@
###
# Copyright (c) 2004-2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
"""
These are commands useful for administrating the bot; they all require their
caller to have the 'admin' capability. This plugin is loaded by default.
"""
import supybot
import supybot.world as world
__author__ = supybot.authors.jemfinch
__maintainer__ = supybot.authors.limnoria_core
# Use this for the version of this plugin. You may wish to put a CVS keyword
# in here if you\'re keeping the plugin in CVS or some similar system.
__version__ = "%%VERSION%%"
# This is a dictionary mapping supybot.Author instances to lists of
# contributions.
__contributors__ = {}
from . import config
from . import plugin
from importlib import reload
reload(plugin) # In case we're being reloaded.
if world.testing:
from . import test
Class = plugin.Class
configure = config.configure

View File

@ -1,47 +0,0 @@
###
# Copyright (c) 2004-2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import supybot.conf as conf
import supybot.registry as registry
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Admin')
def configure(advanced):
# This will be called by supybot to configure this module. advanced is
# a bool that specifies whether the user identified themself as an advanced
# user or not. You should effect your configuration by manipulating the
# registry as appropriate.
from supybot.questions import expect, anything, something, yn
conf.registerPlugin('Admin', True)
Admin = conf.registerPlugin('Admin')
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,270 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Supybot\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2011-10-31 13:37+0100\n"
"Last-Translator: Florian Besser <fbesser@gmail.com>\n"
"Language-Team: German <fbesser@gmail.com>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Poedit-Language: German\n"
"X-Poedit-Country: Germany\n"
#: plugin.py:46
msgid ""
"This plugin provides access to administrative commands, such as\n"
" adding capabilities, managing ignore lists, and joining channels.\n"
" This is a core Supybot plugin that should not be removed!"
msgstr ""
#: plugin.py:57
msgid "Nick/channel temporarily unavailable."
msgstr "Nick/Kanal temporär nicht verfügbar."
#: plugin.py:85
msgid "Cannot join %s, it's full."
msgstr "Kann %s nicht beitreten, der Kanal ist voll."
#: plugin.py:93
msgid "Cannot join %s, I was not invited."
msgstr "Kann %s nicht beitreten, ich wurde nicht eingeladen."
#: plugin.py:101
msgid "Cannot join %s, I am banned."
msgstr "Ich kann %s nicht betreten, ich bin gebannt."
#: plugin.py:109
msgid "Cannot join %s, my keyword was wrong."
msgstr "Ich kann %s nicht beitreten, mein Schlüsselwort ist falsch."
#: plugin.py:117 plugin.py:126
msgid "Cannot join %s, I'm not identified with NickServ."
msgstr "Ich kann %s nicht betreten, ich bin nicht mit NickServ identifiziert."
#: plugin.py:156
msgid ""
"<channel> [<key>]\n"
"\n"
" Tell the bot to join the given channel. If <key> is given, it is "
"used\n"
" when attempting to join the channel.\n"
" "
msgstr ""
"<Kanal> [<Schlüssel>]\n"
"\n"
"Sagt dem Bot dem angegeben Kanal beizutreten. Falls <Schlüssel> angegeben "
"wird, wird dieser benutzt um zu versuchen den Kanal zu betreten."
#: plugin.py:162
msgid "channel"
msgstr ""
#: plugin.py:169
msgid "I'm already too close to maximum number of channels for this network."
msgstr "Ich bin schon zu nah an den maximalen Kanälen für dieses Netzwerk."
#: plugin.py:178
#, fuzzy
msgid ""
"takes no arguments\n"
"\n"
" Returns the channels the bot is on.\n"
" "
msgstr ""
"hat keine Argumente\n"
"\n"
"Listet die Hostmasken auf, die der Bot ignoriert."
#: plugin.py:187
msgid "I'm not currently in any channels."
msgstr "Momentan bin ich in keinen Kanälen."
#: plugin.py:193
msgid "My connection is restricted, I can't change nicks."
msgstr "Meine Verbindung ist begrenzt, I kann meinen Nick nicht wechseln."
#: plugin.py:200
msgid "Someone else is already using that nick."
msgstr "Jemand anderes benutzt diesen Nick schon."
#: plugin.py:207
#, fuzzy
msgid "I can't change nick, I'm currently banned in %s."
msgstr "Ich kann meinen Nick nicht ändern, der Server sagte %q."
#: plugin.py:215
msgid "I can't change nicks, the server said %q."
msgstr "Ich kann meinen Nick nicht ändern, der Server sagte %q."
#: plugin.py:229
#, fuzzy
msgid ""
"[<nick>] [<network>]\n"
"\n"
" Changes the bot's nick to <nick>. If no nick is given, returns the\n"
" bot's current nick.\n"
" "
msgstr ""
"[<Nick>]\n"
"\n"
"Ändert den Nick des Bots zu <Nick>. Falls <Nick> nicht angegeben wird, wird "
"der momentane Botnick zurückgegeben."
#: plugin.py:248
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Gives the user specified by <name> (or the user to whom "
"<hostmask>\n"
" currently maps) the specified capability <capability>\n"
" "
msgstr ""
"<Name|Hostmaske> <Fähigkeit>\n"
"\n"
"Gibt dem angebenen Benutzer <Name> (oder dem auf den die <Hostmaske> "
"zutrifft) die angegebene Fähigkeit."
#: plugin.py:268
msgid ""
"The \"owner\" capability can't be added in the bot. Use the supybot-adduser "
"program (or edit the users.conf file yourself) to add an owner capability."
msgstr ""
"Die \"owner\" Fähigkeit kann nicht über den Bot hinzugefügt werden. Benutze "
"das supybot-adduser Programm (oder verändere users.conf per Hand) um die "
"Besitzer Fähigkeit hinzuzufügen."
#: plugin.py:279
msgid "You can't add capabilities you don't have."
msgstr "Du kannst keine Fähigkeiten hinzufügen, die du nicht hast."
#: plugin.py:284
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Takes from the user specified by <name> (or the user to whom\n"
" <hostmask> currently maps) the specified capability "
"<capability>\n"
" "
msgstr ""
"<Name|Hostmaske> <Fähigkeit>\n"
"\n"
"Nimmt dem Benutzer der durch <Name> (oder dem Benutzer auf den momentan "
"<Hostmaske> zeigt) angeben wird die angegeben Fähigkeit <Fähigkeit>."
#: plugin.py:296
msgid "That user doesn't have that capability."
msgstr "Der Benutzer hat diese Fähigkeit nicht."
#: plugin.py:298
msgid "You can't remove capabilities you don't have."
msgstr "Du kannst keine Fähigkeiten entfernen, die du nicht hast."
#: plugin.py:306
msgid ""
"<hostmask|nick> [<expires>]\n"
"\n"
" This will set a persistent ignore on <hostmask> or the hostmask\n"
" currently associated with <nick>. <expires> is an optional "
"argument\n"
" specifying when (in \"seconds from now\") the ignore will "
"expire; if\n"
" it isn't given, the ignore will never automatically expire.\n"
" "
msgstr ""
"<Hostmaske|Nick> [<Ablaufzeitpunkt>]\n"
"\n"
"Es wird eine beständige Ignorierung auf <Hostmaske> oder auf die Hostmaske "
"die momentan mit <Nick> verbunden wird gesetzt. <Ablaufzeitpunkt> ist "
"optional, das legt fest wann die Ignorierung abläuft;falls dies nicht "
"angegeben wird, wird die Ignorierung niemals ablaufen."
#: plugin.py:319
msgid ""
"<hostmask|nick>\n"
"\n"
" This will remove the persistent ignore on <hostmask> or the\n"
" hostmask currently associated with <nick>.\n"
" "
msgstr ""
"<Hostmaske|Nick>\n"
"\n"
"Wird die beständige Ignorierung, von <Hostmaske> oder der Hostmaske die "
"momentan mit dem <Nick> verbunden wird, aufheben."
#: plugin.py:328
msgid "%s wasn't in the ignores database."
msgstr "%s war nicht in der Datenbank für Ignorierungen."
#: plugin.py:333
msgid ""
"takes no arguments\n"
"\n"
" Lists the hostmasks that the bot is ignoring.\n"
" "
msgstr ""
"hat keine Argumente\n"
"\n"
"Listet die Hostmasken auf, die der Bot ignoriert."
#: plugin.py:341
msgid "I'm not currently globally ignoring anyone."
msgstr "Momentan ignoriere ich niemanden global."
#: plugin.py:345
msgid ""
"takes no arguments\n"
"\n"
" Clears the current send queue for this network.\n"
" "
msgstr ""
"hat keine Argumente\n"
"\n"
"Leert die momentane Sendenwarteschlange für dieses Netzwerk."
#: plugin.py:354
msgid ""
"<command> [<arg> ...]\n"
"\n"
" Perform <command> (with associated <arg>s on all channels on current "
"network."
msgstr ""
#~ msgid ""
#~ "takes no arguments\n"
#~ "\n"
#~ " Returns the channels the bot is on. Must be given in private, in "
#~ "order\n"
#~ " to protect the secrecy of secret channels.\n"
#~ " "
#~ msgstr ""
#~ "hat keine Argumenten\n"
#~ "\n"
#~ "Gibt die Kanäle aus in denen der Bot sich befindet. Dieser Befehl muss "
#~ "privat gegeben werden, um das Geheimnis der geheimen Kanale zu wahren."
#~ msgid ""
#~ "[<channel>] [<reason>]\n"
#~ "\n"
#~ " Tells the bot to part the list of channels you give it. "
#~ "<channel> is\n"
#~ " only necessary if you want the bot to part a channel other than "
#~ "the\n"
#~ " current channel. If <reason> is specified, use it as the part\n"
#~ " message.\n"
#~ " "
#~ msgstr ""
#~ "[<Kanal>] [<Grund>]\n"
#~ "\n"
#~ "Sagt dem Bot die Liste von angebenen Kanälen zu verlassen. <Kanal> ist "
#~ "nur notwendig, falls der Bot einen anderen Kanal als den Momentanen "
#~ "verlassen soll. Falls <Grund> angegeben wird, wird dies als "
#~ "Verlassensnachricht verwendet."
#~ msgid "I'm not in %s."
#~ msgstr "Ich bin nicht in %s."
#~ msgid "That nick is currently banned."
#~ msgstr "Dieser Nick ist momentan gebannt."

View File

@ -1,295 +0,0 @@
# Admin plugin in Limnoria.
# Copyright (C) 2011 Limnoria
# Mikaela Suomalainen <mikaela.suomalainen@outlook.com>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: Finnish translation of Admin plugin in Supybot\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2014-12-20 12:19+0200\n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: \n"
"Language: fi_FI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 1.6.10\n"
#: plugin.py:46
msgid ""
"This plugin provides access to administrative commands, such as\n"
" adding capabilities, managing ignore lists, and joining channels.\n"
" This is a core Supybot plugin that should not be removed!"
msgstr ""
"Tämä plugin antaa pääsyn ylläpitäviin komentoihin, kuten valtuuksien "
"lisäämiseen,\n"
" ignore-listojen hallintaan ja kanaville liittymiseen. Tämä on ydin Supybot-"
"plugin, jota ei pitäisi poistaa!s"
#: plugin.py:57
msgid "Nick/channel temporarily unavailable."
msgstr "Nimimerkki/kanava on väliaikaisesti saavuttamattomissa."
#: plugin.py:85
msgid "Cannot join %s, it's full."
msgstr "Ei voida liittyä kanavalle %s, se on täynnä."
#: plugin.py:93
msgid "Cannot join %s, I was not invited."
msgstr "Ei voi liittyä kanavalle %s, minua ei ole kutsuttu."
#: plugin.py:101
msgid "Cannot join %s, I am banned."
msgstr "Ei voi liittyä kanavalle %s, se on antanut minulle porttikiellon."
#: plugin.py:109
msgid "Cannot join %s, my keyword was wrong."
msgstr "En voi liittyä kanavalle %s, minun avainsana oli väärä."
#: plugin.py:117 plugin.py:126
msgid "Cannot join %s, I'm not identified with NickServ."
msgstr "En voi liittyä kanavalle %s, koska en ole tunnistautunut NickServille."
#: plugin.py:156
msgid ""
"<channel> [<key>]\n"
"\n"
" Tell the bot to join the given channel. If <key> is given, it is "
"used\n"
" when attempting to join the channel.\n"
" "
msgstr ""
"<kanava> [<avain>]\n"
"\n"
" Käskee botin liittyä annetulle kanavalle. Jos <avain> on annettu, "
"sitä käytetään\n"
" yrittäessä liittyä kanavalle.\n"
" "
#: plugin.py:162
msgid "channel"
msgstr ""
#: plugin.py:169
msgid "I'm already too close to maximum number of channels for this network."
msgstr "Minä olen jo liian lähellä kanavien maksimimäärää tässä verkossa."
#: plugin.py:178
#, fuzzy
msgid ""
"takes no arguments\n"
"\n"
" Returns the channels the bot is on.\n"
" "
msgstr ""
"Ei ota parametrejä\n"
"\n"
" Luetteloi hostmaskit jotka ovat botin huomiotta jättämis listalla.\n"
" "
#: plugin.py:187
msgid "I'm not currently in any channels."
msgstr "En juuri nyt ole millään kanavalla."
#: plugin.py:193
msgid "My connection is restricted, I can't change nicks."
msgstr "Minun yhteyteni on rajoitettu. En voi vaihtaa nimimerkkiä."
#: plugin.py:200
msgid "Someone else is already using that nick."
msgstr "Joku muu käyttää jo tuota nimimerkkiä."
#: plugin.py:207
#, fuzzy
msgid "I can't change nick, I'm currently banned in %s."
msgstr "Minä en voi vaihtaa nimimerkkiä, koska palvelin sanoi %q"
#: plugin.py:215
msgid "I can't change nicks, the server said %q."
msgstr "Minä en voi vaihtaa nimimerkkiä, koska palvelin sanoi %q"
#: plugin.py:229
msgid ""
"[<nick>] [<network>]\n"
"\n"
" Changes the bot's nick to <nick>. If no nick is given, returns the\n"
" bot's current nick.\n"
" "
msgstr ""
"[<nimimerkki>] [<verkko>]\n"
"\n"
" Vaihtaa botin nimimerkin <nimimerkiksi>. Mikäli nimimerkkiä ei anneta, "
"botin nykyinen\n"
" nimimerkki palautetaan.\n"
" "
#: plugin.py:248
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Gives the user specified by <name> (or the user to whom "
"<hostmask>\n"
" currently maps) the specified capability <capability>\n"
" "
msgstr ""
"<nimi|hostmask> <valtuus>\n"
"\n"
" Antaa <nimen> määrittämälle käyttäjälle (tai käyttäjälle jonka "
"<hostmask>\n"
" ilmoittaa) määritetyn valtuuden <valtuus>\n"
" "
#: plugin.py:268
msgid ""
"The \"owner\" capability can't be added in the bot. Use the supybot-adduser "
"program (or edit the users.conf file yourself) to add an owner capability."
msgstr ""
"\"Owner\" valtuutta ei voi lisätä botissa. Käytä supybot-adduser ohjelmaa "
"(tai muokkaa users.conf tiedostoa itse) lisätäksesi owner valtuuden."
#: plugin.py:279
msgid "You can't add capabilities you don't have."
msgstr "Et voi lisätä valtuuksia, joita sinulla ei ole."
#: plugin.py:284
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Takes from the user specified by <name> (or the user to whom\n"
" <hostmask> currently maps) the specified capability "
"<capability>\n"
" "
msgstr ""
"<nimi|hostmask> <valtuus>\n"
"\n"
" Ottaa <nimen> määrittämältä käyttäjältä (tai käyttäjältä "
"johon\n"
" <hostmask> sopii) määritetyn valtuuden <valtuus>\n"
" "
#: plugin.py:296
msgid "That user doesn't have that capability."
msgstr "Tuolla käyttäjällä ei tuota valtuutta."
#: plugin.py:298
msgid "You can't remove capabilities you don't have."
msgstr "Sinä et voi poistaa valtuuksia, joita sinulla ei ole."
#: plugin.py:306
msgid ""
"<hostmask|nick> [<expires>]\n"
"\n"
" This will set a persistent ignore on <hostmask> or the hostmask\n"
" currently associated with <nick>. <expires> is an optional "
"argument\n"
" specifying when (in \"seconds from now\") the ignore will "
"expire; if\n"
" it isn't given, the ignore will never automatically expire.\n"
" "
msgstr ""
"<hostmask|nimimerkki> [<vanhentuu>]\n"
"\n"
" Tämä asettaa pysyvän huomiotta jättämisen <hostmaskiin> tai "
"hostmaskiin,\n"
" joka on tällä hetkellä yhdistetty <nimimerkkiin>. <Vanhentuminen> on "
"vaihtoehtoinen paremetri,\n"
" joka määrittää (\"sekuntit\") joiden jälkeen huomiotta jättäminen "
"poistetaan; jos\n"
" sitä ei ole annettu, huomiotta jättäminen ei vanhene ikinä "
"automaattisesti.\n"
" "
#: plugin.py:319
msgid ""
"<hostmask|nick>\n"
"\n"
" This will remove the persistent ignore on <hostmask> or the\n"
" hostmask currently associated with <nick>.\n"
" "
msgstr ""
"<hostmask|nimimerkki>\n"
"\n"
" Tämä poistaa pysyvän huomiotta jättämisen <hostmaskista> tai\n"
" hostmaskista joka on tällä hetkellä yhdistetty <nimimerkkiin>.\n"
" "
#: plugin.py:328
msgid "%s wasn't in the ignores database."
msgstr "%s ei ollut huomiotta jätettävien tietokannassa."
#: plugin.py:333
msgid ""
"takes no arguments\n"
"\n"
" Lists the hostmasks that the bot is ignoring.\n"
" "
msgstr ""
"Ei ota parametrejä\n"
"\n"
" Luetteloi hostmaskit jotka ovat botin huomiotta jättämis listalla.\n"
" "
#: plugin.py:341
msgid "I'm not currently globally ignoring anyone."
msgstr "En tällä hetkellä jätä ketään huomioitta globaalisti."
#: plugin.py:345
msgid ""
"takes no arguments\n"
"\n"
" Clears the current send queue for this network.\n"
" "
msgstr ""
"ei ota parametrejä\n"
"\n"
" Tyhjentää nykyisen lähetysjonon tälle verkolle.\n"
" "
#: plugin.py:354
msgid ""
"<command> [<arg> ...]\n"
"\n"
" Perform <command> (with associated <arg>s on all channels on current "
"network."
msgstr ""
#~ msgid ""
#~ "takes no arguments\n"
#~ "\n"
#~ " Returns the channels the bot is on. Must be given in private, in "
#~ "order\n"
#~ " to protect the secrecy of secret channels.\n"
#~ " "
#~ msgstr ""
#~ "Ei ota parametrejä\n"
#~ "\n"
#~ " Palauttaa listan kanavista, joilla botti on. Täytyy antaa "
#~ "yksityisviestillä salaistenkanavien\n"
#~ " salaisuuden suojelemiseksi.\n"
#~ " "
#~ msgid ""
#~ "[<channel>] [<reason>]\n"
#~ "\n"
#~ " Tells the bot to part the list of channels you give it. "
#~ "<channel> is\n"
#~ " only necessary if you want the bot to part a channel other than "
#~ "the\n"
#~ " current channel. If <reason> is specified, use it as the part\n"
#~ " message.\n"
#~ " "
#~ msgstr ""
#~ "[<kanava>] [<syy>]\n"
#~ "\n"
#~ " Käskee botin poistua kanavilta, jotka annat sille. <Kanava> on\n"
#~ " vaadittu jos haluat botin poistuvat muulta, kuin \n"
#~ " nykyiseltä kanavalta. Jos <syy> on määritetty, sitä käytetään\n"
#~ " poistumisviestissä.\n"
#~ " "
#~ msgid "I'm not in %s."
#~ msgstr "Minä en ole kanavalla %s."
#~ msgid "That nick is currently banned."
#~ msgstr "Tuolla nimimerkillä on tällähetkellä porttikielto."

View File

@ -1,268 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: ProgVal <progval@gmail.com>\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: Ascii\n"
"X-Generator: Poedit 1.5.4\n"
#: plugin.py:46
msgid ""
"This plugin provides access to administrative commands, such as\n"
" adding capabilities, managing ignore lists, and joining channels.\n"
" This is a core Supybot plugin that should not be removed!"
msgstr ""
#: plugin.py:57
msgid "Nick/channel temporarily unavailable."
msgstr "Nick/canal temporairement indisponible"
#: plugin.py:85
msgid "Cannot join %s, it's full."
msgstr "Ne peut joindre %s, il est plein."
#: plugin.py:93
msgid "Cannot join %s, I was not invited."
msgstr "Ne peut joindre %s, pas invité."
#: plugin.py:101
msgid "Cannot join %s, I am banned."
msgstr "Ne peut joindre %s, j'y suis banni."
#: plugin.py:109
msgid "Cannot join %s, my keyword was wrong."
msgstr "Ne peut joindre %s, mon mot de passe est mauvais."
#: plugin.py:117 plugin.py:126
msgid "Cannot join %s, I'm not identified with NickServ."
msgstr "Ne peut joindre %s, je ne suis pas identifié auprès de NickServ."
#: plugin.py:156
msgid ""
"<channel> [<key>]\n"
"\n"
" Tell the bot to join the given channel. If <key> is given, it is "
"used\n"
" when attempting to join the channel.\n"
" "
msgstr ""
"<canal> [<clef>]\n"
"\n"
"Dit au bot de rejoindre le canal donné. Si la <clef> est donnée, elle est "
"utilisée pour rejoindre le canal."
#: plugin.py:162
msgid "channel"
msgstr ""
#: plugin.py:169
msgid "I'm already too close to maximum number of channels for this network."
msgstr "Je suis déjà sur un nombre de canaux trop grand pour ce réseau."
#: plugin.py:178
#, fuzzy
msgid ""
"takes no arguments\n"
"\n"
" Returns the channels the bot is on.\n"
" "
msgstr ""
"Ne prend pas d'argument\n"
"\n"
"Liste les masques d'hôte que le bot ignore."
#: plugin.py:187
msgid "I'm not currently in any channels."
msgstr "Je ne suis actuellement sur aucun canal."
#: plugin.py:193
msgid "My connection is restricted, I can't change nicks."
msgstr "Ma connexion est restreinte, je ne peux changer de nick."
#: plugin.py:200
msgid "Someone else is already using that nick."
msgstr "Quelqu'un d'autre utilise déjà ce nick."
#: plugin.py:207
#, fuzzy
msgid "I can't change nick, I'm currently banned in %s."
msgstr "Je ne peux changer de nick, le serveur a dit %q."
#: plugin.py:215
msgid "I can't change nicks, the server said %q."
msgstr "Je ne peux changer de nick, le serveur a dit %q."
#: plugin.py:229
msgid ""
"[<nick>] [<network>]\n"
"\n"
" Changes the bot's nick to <nick>. If no nick is given, returns the\n"
" bot's current nick.\n"
" "
msgstr ""
"[<nick>] [<réseau>]\n"
"\n"
"Change le nick du bot à <nick>. Si aucun nick n'est donné, retourne le nick "
"actuel du bot."
#: plugin.py:248
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Gives the user specified by <name> (or the user to whom "
"<hostmask>\n"
" currently maps) the specified capability <capability>\n"
" "
msgstr ""
"<nom|masque d'hôte> <capacité>\n"
"\n"
"Donne la <capacité> à l'utilisateur spécifié par <nom> (ou l'utilisateur à "
"qui correspond <masque d'hôte>)."
#: plugin.py:268
msgid ""
"The \"owner\" capability can't be added in the bot. Use the supybot-adduser "
"program (or edit the users.conf file yourself) to add an owner capability."
msgstr ""
"La capacité \"owner\" ne peut être ajoutée via le bot. Utilisez le programme "
"supybot-adduser (ou éditez le fichier users.conf vous-même) pour ajouter la "
"capacité owner."
#: plugin.py:279
msgid "You can't add capabilities you don't have."
msgstr "Vous ne pouvez ajouter des capacités que vous n'avez pas."
#: plugin.py:284
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Takes from the user specified by <name> (or the user to whom\n"
" <hostmask> currently maps) the specified capability "
"<capability>\n"
" "
msgstr ""
"<nom|masque d'hôte> <capacité>\n"
"\n"
"Retire la <capacité> à l'utilisateur spécifié par le <nom> (ou celui à qui "
"correspond le <masque d'hôte>)."
#: plugin.py:296
msgid "That user doesn't have that capability."
msgstr "Cet utilisateur n'a pas cette capacité."
#: plugin.py:298
msgid "You can't remove capabilities you don't have."
msgstr "Vous ne pouvez retirer des capacités que vous n'avez pas."
#: plugin.py:306
msgid ""
"<hostmask|nick> [<expires>]\n"
"\n"
" This will set a persistent ignore on <hostmask> or the hostmask\n"
" currently associated with <nick>. <expires> is an optional "
"argument\n"
" specifying when (in \"seconds from now\") the ignore will "
"expire; if\n"
" it isn't given, the ignore will never automatically expire.\n"
" "
msgstr ""
"<masque d'hôte|nick> [<expiration>]\n"
"\n"
"Ajoute un masque d'ignorance persistant sur le <masque d'hôte>, ou sur le "
"masque d'hôte de <nick>. <expiration> est un argument optionnel spécifiant "
"quand (en \"secondes à partir de maintenant\") l'ignorance expirera ; si "
"elle n'est pas donnée, l'ignorance n'expirera jamais."
#: plugin.py:319
msgid ""
"<hostmask|nick>\n"
"\n"
" This will remove the persistent ignore on <hostmask> or the\n"
" hostmask currently associated with <nick>.\n"
" "
msgstr ""
"<masque d'hôte|nick>\n"
"\n"
"Ceci retirera le masque d'ignorance persistant sur le <masque d'hôte>, ou "
"sur le masque d'hôte associé au <nick>."
#: plugin.py:328
msgid "%s wasn't in the ignores database."
msgstr "%s n'étais pas dans ma base de données d'ignorance."
#: plugin.py:333
msgid ""
"takes no arguments\n"
"\n"
" Lists the hostmasks that the bot is ignoring.\n"
" "
msgstr ""
"Ne prend pas d'argument\n"
"\n"
"Liste les masques d'hôte que le bot ignore."
#: plugin.py:341
msgid "I'm not currently globally ignoring anyone."
msgstr "Je n'ignore actuellement personne globalement."
#: plugin.py:345
msgid ""
"takes no arguments\n"
"\n"
" Clears the current send queue for this network.\n"
" "
msgstr ""
"Ne prend pas d'argument\n"
"\n"
"Vide la queue en attente pour ce réseau."
#: plugin.py:354
msgid ""
"<command> [<arg> ...]\n"
"\n"
" Perform <command> (with associated <arg>s on all channels on current "
"network."
msgstr ""
#~ msgid ""
#~ "takes no arguments\n"
#~ "\n"
#~ " Returns the channels the bot is on. Must be given in private, in "
#~ "order\n"
#~ " to protect the secrecy of secret channels.\n"
#~ " "
#~ msgstr ""
#~ "Ne prend pas d'argument \n"
#~ "\n"
#~ "Retourne les canaux sur lesquels le bot est. Doit être en privé, dans le "
#~ "but d'éviter que les canaux secrets ne soient divulgués."
#~ msgid ""
#~ "[<channel>] [<reason>]\n"
#~ "\n"
#~ " Tells the bot to part the list of channels you give it. "
#~ "<channel> is\n"
#~ " only necessary if you want the bot to part a channel other than "
#~ "the\n"
#~ " current channel. If <reason> is specified, use it as the part\n"
#~ " message.\n"
#~ " "
#~ msgstr ""
#~ "[<canal>] [<raison>]\n"
#~ "\n"
#~ "Dit au bot de partir de la liste de canaux que vous avez donnée. <canal> "
#~ "n'est nécessaire que si vous voulez que le bot parte d'un autre canal que "
#~ "l'actuel. Si la <raison> est spécifiée, elle est utilisée comme message "
#~ "de départ."
#~ msgid "I'm not in %s."
#~ msgstr "Je ne suis pas sur %s."
#~ msgid "That nick is currently banned."
#~ msgstr "Ce nick est banni."

View File

@ -1,287 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2012-03-15 20:25+0100\n"
"Last-Translator: skizzhg <skizzhg@gmx.com>\n"
"Language-Team: Italian <skizzhg@gmx.com>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: plugin.py:46
msgid ""
"This plugin provides access to administrative commands, such as\n"
" adding capabilities, managing ignore lists, and joining channels.\n"
" This is a core Supybot plugin that should not be removed!"
msgstr ""
#: plugin.py:57
msgid "Nick/channel temporarily unavailable."
msgstr "Nick/canale temporaneamente non disponibile."
#: plugin.py:85
msgid "Cannot join %s, it's full."
msgstr "Non posso entrare in %s, è pieno."
#: plugin.py:93
msgid "Cannot join %s, I was not invited."
msgstr "Non posso entrare in %s, non sono stato invitato."
#: plugin.py:101
msgid "Cannot join %s, I am banned."
msgstr "Non posso entrare in %s, sono stato bannato."
#: plugin.py:109
msgid "Cannot join %s, my keyword was wrong."
msgstr "Non posso entrare in %s, la password era sbagliata."
#: plugin.py:117 plugin.py:126
msgid "Cannot join %s, I'm not identified with NickServ."
msgstr "Non posso entrare in %s, non sono identificato con NickServ."
#: plugin.py:156
msgid ""
"<channel> [<key>]\n"
"\n"
" Tell the bot to join the given channel. If <key> is given, it is "
"used\n"
" when attempting to join the channel.\n"
" "
msgstr ""
"<canale> [<password>]\n"
"\n"
" Dice al bot di entrare nel canale specificato. Se <password> è "
"fornita,\n"
" viene usata quando si tenta di entrare nel canale.\n"
" "
#: plugin.py:162
msgid "channel"
msgstr ""
#: plugin.py:169
msgid "I'm already too close to maximum number of channels for this network."
msgstr "Sono già troppo vicino al numero massimo di canali per questa rete."
#: plugin.py:178
#, fuzzy
msgid ""
"takes no arguments\n"
"\n"
" Returns the channels the bot is on.\n"
" "
msgstr ""
"Non necessita argomenti\n"
"\n"
" Elenca le hostmask che il bot sta ignorando.\n"
" "
#: plugin.py:187
msgid "I'm not currently in any channels."
msgstr "Al momento non sono in nessun canale."
#: plugin.py:193
msgid "My connection is restricted, I can't change nicks."
msgstr "La mia connessione è limitata, non posso cambiare nick."
#: plugin.py:200
msgid "Someone else is already using that nick."
msgstr "Qualcun altro sta utilizzando questo nick."
#: plugin.py:207
#, fuzzy
msgid "I can't change nick, I'm currently banned in %s."
msgstr "Non posso cambiare nick, il server ha detto %q."
#: plugin.py:215
msgid "I can't change nicks, the server said %q."
msgstr "Non posso cambiare nick, il server ha detto %q."
#: plugin.py:229
#, fuzzy
msgid ""
"[<nick>] [<network>]\n"
"\n"
" Changes the bot's nick to <nick>. If no nick is given, returns the\n"
" bot's current nick.\n"
" "
msgstr ""
"[<nick>]\n"
"\n"
" Cambia il nick del bot in <nick>. Se non ne viene fornito uno, "
"restituisce\n"
" quello attuale.\n"
" "
#: plugin.py:248
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Gives the user specified by <name> (or the user to whom "
"<hostmask>\n"
" currently maps) the specified capability <capability>\n"
" "
msgstr ""
"<nome|hostmask> <capacità>\n"
"\n"
" Dà all'utente specificato da <nome> (o quello a cui corrisponde\n"
" <hostmask> attualmente) la <capacità> specificata.\n"
" "
#: plugin.py:268
msgid ""
"The \"owner\" capability can't be added in the bot. Use the supybot-adduser "
"program (or edit the users.conf file yourself) to add an owner capability."
msgstr ""
"La capacità \"owner\" non può essere aggiunta al bot. Utilizzare il "
"programma supybot-adduser (o modificare il file users.conf) per aggiungerla."
#: plugin.py:279
msgid "You can't add capabilities you don't have."
msgstr "Non puoi aggiungere capacità che non hai."
#: plugin.py:284
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Takes from the user specified by <name> (or the user to whom\n"
" <hostmask> currently maps) the specified capability "
"<capability>\n"
" "
msgstr ""
"<nome|hostmask> <capacità>\n"
"\n"
" Rimuove l'utente specificato da <nome> (o quello a cui "
"corrisponde\n"
" <hostmask> attualmente) la <capacità> specificata\n"
" "
#: plugin.py:296
msgid "That user doesn't have that capability."
msgstr "Questo utente non ha tale capacità."
#: plugin.py:298
msgid "You can't remove capabilities you don't have."
msgstr "Non puoi rimuovere capacità che non hai."
#: plugin.py:306
msgid ""
"<hostmask|nick> [<expires>]\n"
"\n"
" This will set a persistent ignore on <hostmask> or the hostmask\n"
" currently associated with <nick>. <expires> is an optional "
"argument\n"
" specifying when (in \"seconds from now\") the ignore will "
"expire; if\n"
" it isn't given, the ignore will never automatically expire.\n"
" "
msgstr ""
"<hostmask|nick> [<scadenza>]\n"
"\n"
" Imposta un ignore permanente su <hostmask> o l'hostmask "
"attualmente\n"
" associata a <nick>. <scadenza> è un argomento opzionale per "
"specificare\n"
" quando (in \"secondi a partire da subito\") scadrà l'ignore; se "
"non fornito,\n"
" questo non scadrà mai.\n"
" "
#: plugin.py:319
msgid ""
"<hostmask|nick>\n"
"\n"
" This will remove the persistent ignore on <hostmask> or the\n"
" hostmask currently associated with <nick>.\n"
" "
msgstr ""
"<hostmask|nick>\n"
"\n"
" Rimuove l'ignore persistente su <hostmask> o l'attuale hostmask "
"associata a <nick>.\n"
" "
#: plugin.py:328
msgid "%s wasn't in the ignores database."
msgstr "%s non è nel mio database degli ignorati."
#: plugin.py:333
msgid ""
"takes no arguments\n"
"\n"
" Lists the hostmasks that the bot is ignoring.\n"
" "
msgstr ""
"Non necessita argomenti\n"
"\n"
" Elenca le hostmask che il bot sta ignorando.\n"
" "
#: plugin.py:341
msgid "I'm not currently globally ignoring anyone."
msgstr "Al momento non sto ignorando nessuno."
#: plugin.py:345
msgid ""
"takes no arguments\n"
"\n"
" Clears the current send queue for this network.\n"
" "
msgstr ""
"non necessita argomenti\n"
"\n"
" Pulisce l'attuale coda dei messaggi da inviare (interrompe il flood) "
"per questa rete.\n"
" "
#: plugin.py:354
msgid ""
"<command> [<arg> ...]\n"
"\n"
" Perform <command> (with associated <arg>s on all channels on current "
"network."
msgstr ""
#~ msgid ""
#~ "takes no arguments\n"
#~ "\n"
#~ " Returns the channels the bot is on. Must be given in private, in "
#~ "order\n"
#~ " to protect the secrecy of secret channels.\n"
#~ " "
#~ msgstr ""
#~ "non necessita argomenti\n"
#~ "\n"
#~ " Restituisce i canali dove è presente il bot. Deve essere "
#~ "richiesto in\n"
#~ " privato per preservare la segretezza dei canali privati.\n"
#~ " "
#~ msgid ""
#~ "[<channel>] [<reason>]\n"
#~ "\n"
#~ " Tells the bot to part the list of channels you give it. "
#~ "<channel> is\n"
#~ " only necessary if you want the bot to part a channel other than "
#~ "the\n"
#~ " current channel. If <reason> is specified, use it as the part\n"
#~ " message.\n"
#~ " "
#~ msgstr ""
#~ "[<canale>] [<motivo>]\n"
#~ "\n"
#~ " Fornisce al bot l'elenco dei canali da cui uscire. <canale> è "
#~ "necessario\n"
#~ " solo se si vuole far uscire il bot da un canale diverso da quello "
#~ "attuale.\n"
#~ " Se <motivo> viene specificato, verrà usato come messaggio di "
#~ "uscita.\n"
#~ " "
#~ msgid "I'm not in %s."
#~ msgstr "Non sono in %s."
#~ msgid "That nick is currently banned."
#~ msgstr "Il nick è attualmente bannato."

View File

@ -1,199 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: plugin.py:46
#, docstring
msgid ""
"This plugin provides access to administrative commands, such as\n"
" adding capabilities, managing ignore lists, and joining channels.\n"
" This is a core Supybot plugin that should not be removed!"
msgstr ""
#: plugin.py:57
#, docstring
msgid "Nick/channel temporarily unavailable."
msgstr ""
#: plugin.py:85
msgid "Cannot join %s, it's full."
msgstr ""
#: plugin.py:93
msgid "Cannot join %s, I was not invited."
msgstr ""
#: plugin.py:101
msgid "Cannot join %s, I am banned."
msgstr ""
#: plugin.py:109
msgid "Cannot join %s, my keyword was wrong."
msgstr ""
#: plugin.py:117 plugin.py:126
msgid "Cannot join %s, I'm not identified with NickServ."
msgstr ""
#: plugin.py:156
#, docstring
msgid ""
"<channel> [<key>]\n"
"\n"
" Tell the bot to join the given channel. If <key> is given, it is used\n"
" when attempting to join the channel.\n"
" "
msgstr ""
#: plugin.py:162
msgid "channel"
msgstr ""
#: plugin.py:169
msgid "I'm already too close to maximum number of channels for this network."
msgstr ""
#: plugin.py:178
#, docstring
msgid ""
"takes no arguments\n"
"\n"
" Returns the channels the bot is on.\n"
" "
msgstr ""
#: plugin.py:187
msgid "I'm not currently in any channels."
msgstr ""
#: plugin.py:193
msgid "My connection is restricted, I can't change nicks."
msgstr ""
#: plugin.py:200
msgid "Someone else is already using that nick."
msgstr ""
#: plugin.py:207
msgid "I can't change nick, I'm currently banned in %s."
msgstr ""
#: plugin.py:215
msgid "I can't change nicks, the server said %q."
msgstr ""
#: plugin.py:229
#, docstring
msgid ""
"[<nick>] [<network>]\n"
"\n"
" Changes the bot's nick to <nick>. If no nick is given, returns the\n"
" bot's current nick.\n"
" "
msgstr ""
#: plugin.py:248
#, docstring
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Gives the user specified by <name> (or the user to whom <hostmask>\n"
" currently maps) the specified capability <capability>\n"
" "
msgstr ""
#: plugin.py:268
msgid "The \"owner\" capability can't be added in the bot. Use the supybot-adduser program (or edit the users.conf file yourself) to add an owner capability."
msgstr ""
#: plugin.py:279
msgid "You can't add capabilities you don't have."
msgstr ""
#: plugin.py:284
#, docstring
msgid ""
"<name|hostmask> <capability>\n"
"\n"
" Takes from the user specified by <name> (or the user to whom\n"
" <hostmask> currently maps) the specified capability <capability>\n"
" "
msgstr ""
#: plugin.py:296
msgid "That user doesn't have that capability."
msgstr ""
#: plugin.py:298
msgid "You can't remove capabilities you don't have."
msgstr ""
#: plugin.py:306
#, docstring
msgid ""
"<hostmask|nick> [<expires>]\n"
"\n"
" This will set a persistent ignore on <hostmask> or the hostmask\n"
" currently associated with <nick>. <expires> is an optional argument\n"
" specifying when (in \"seconds from now\") the ignore will expire; if\n"
" it isn't given, the ignore will never automatically expire.\n"
" "
msgstr ""
#: plugin.py:319
#, docstring
msgid ""
"<hostmask|nick>\n"
"\n"
" This will remove the persistent ignore on <hostmask> or the\n"
" hostmask currently associated with <nick>.\n"
" "
msgstr ""
#: plugin.py:328
msgid "%s wasn't in the ignores database."
msgstr ""
#: plugin.py:333
#, docstring
msgid ""
"takes no arguments\n"
"\n"
" Lists the hostmasks that the bot is ignoring.\n"
" "
msgstr ""
#: plugin.py:341
msgid "I'm not currently globally ignoring anyone."
msgstr ""
#: plugin.py:345
#, docstring
msgid ""
"takes no arguments\n"
"\n"
" Clears the current send queue for this network.\n"
" "
msgstr ""
#: plugin.py:354
#, docstring
msgid ""
"<command> [<arg> ...]\n"
"\n"
" Perform <command> (with associated <arg>s on all channels on current network."
msgstr ""

View File

@ -1,367 +0,0 @@
###
# Copyright (c) 2002-2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import sys
import time
import supybot.conf as conf
import supybot.ircdb as ircdb
import supybot.utils as utils
from supybot.commands import *
import supybot.ircmsgs as ircmsgs
import supybot.ircutils as ircutils
import supybot.schedule as schedule
import supybot.callbacks as callbacks
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Admin')
class Admin(callbacks.Plugin):
"""This plugin provides access to administrative commands, such as
adding capabilities, managing ignore lists, and joining channels.
This is a core Supybot plugin that should not be removed!"""
def __init__(self, irc):
self.__parent = super(Admin, self)
self.__parent.__init__(irc)
self.joins = {}
self.pendingNickChanges = {}
@internationalizeDocstring
def do437(self, irc, msg):
"""Nick/channel temporarily unavailable."""
target = msg.args[0]
t = time.time() + 30
if irc.isChannel(target):
# Let's schedule a rejoin.
networkGroup = conf.supybot.networks.get(irc.network)
def rejoin():
irc.queueMsg(networkGroup.channels.join(target))
# We don't need to schedule something because we'll get another
# 437 when we try to join later.
schedule.addEvent(rejoin, t)
self.log.info('Scheduling a rejoin to %s at %s; '
'Channel temporarily unavailable.', target, t)
else:
irc = self.pendingNickChanges.get(irc, None)
if irc is not None:
def nick():
irc.queueMsg(ircmsgs.nick(target))
schedule.addEvent(nick, t)
self.log.info('Scheduling a nick change to %s at %s; '
'Nick temporarily unavailable.', target, t)
else:
self.log.debug('Got 437 without Admin.nick being called.')
def do471(self, irc, msg):
try:
channel = msg.args[1]
(irc, msg) = self.joins.pop(channel)
irc.error(_('Cannot join %s, it\'s full.') % channel)
except KeyError:
self.log.debug('Got 471 without Admin.join being called.')
def do473(self, irc, msg):
try:
channel = msg.args[1]
(irc, msg) = self.joins.pop(channel)
irc.error(_('Cannot join %s, I was not invited.') % channel)
except KeyError:
self.log.debug('Got 473 without Admin.join being called.')
def do474(self, irc, msg):
try:
channel = msg.args[1]
(irc, msg) = self.joins.pop(channel)
irc.error(_('Cannot join %s, I am banned.') % channel)
except KeyError:
self.log.debug('Got 474 without Admin.join being called.')
def do475(self, irc, msg):
try:
channel = msg.args[1]
(irc, msg) = self.joins.pop(channel)
irc.error(_('Cannot join %s, my keyword was wrong.') % channel)
except KeyError:
self.log.debug('Got 475 without Admin.join being called.')
def do477(self, irc, msg):
try:
channel = msg.args[1]
(irc,msg) = self.joins.pop(channel)
irc.error(_('Cannot join %s, I\'m not identified with '
'NickServ.') % channel)
except KeyError:
self.log.debug('Got 477 without Admin.join being called.')
def do515(self, irc, msg):
try:
channel = msg.args[1]
(irc, msg) = self.joins.pop(channel)
irc.error(_('Cannot join %s, I\'m not identified with '
'NickServ.') % channel)
except KeyError:
self.log.debug('Got 515 without Admin.join being called.')
def doJoin(self, irc, msg):
if msg.prefix == irc.prefix:
try:
del self.joins[msg.args[0]]
except KeyError:
s = 'Joined a channel without Admin.join being called.'
self.log.debug(s)
def doInvite(self, irc, msg):
channel = msg.args[1]
if channel not in irc.state.channels:
if conf.supybot.alwaysJoinOnInvite.get(channel)() or \
ircdb.checkCapability(msg.prefix, 'admin'):
self.log.info('Invited to %s by %s.', channel, msg.prefix)
networkGroup = conf.supybot.networks.get(irc.network)
irc.queueMsg(networkGroup.channels.join(channel))
conf.supybot.networks.get(irc.network).channels().add(channel)
else:
self.log.warning('Invited to %s by %s, but '
'supybot.alwaysJoinOnInvite was False and '
'the user lacked the "admin" capability.',
channel, msg.prefix)
@internationalizeDocstring
def join(self, irc, msg, args, channel, key):
"""<channel> [<key>]
Tell the bot to join the given channel. If <key> is given, it is used
when attempting to join the channel.
"""
if not irc.isChannel(channel):
irc.errorInvalid(_('channel'), channel, Raise=True)
networkGroup = conf.supybot.networks.get(irc.network)
networkGroup.channels().add(channel)
if key:
networkGroup.channels.key.get(channel).setValue(key)
maxchannels = irc.state.supported.get('maxchannels', sys.maxsize)
if len(irc.state.channels) + 1 > maxchannels:
irc.error(_('I\'m already too close to maximum number of '
'channels for this network.'), Raise=True)
irc.queueMsg(networkGroup.channels.join(channel))
irc.noReply()
self.joins[channel] = (irc, msg)
join = wrap(join, ['validChannel', additional('something')])
@internationalizeDocstring
def channels(self, irc, msg, args):
"""takes no arguments
Returns the channels the bot is on.
"""
L = irc.state.channels.keys()
if L:
utils.sortBy(ircutils.toLower, L)
irc.reply(format('%L', L), private=True)
else:
irc.reply(_('I\'m not currently in any channels.'))
channels = wrap(channels)
def do484(self, irc, msg):
irc = self.pendingNickChanges.get(irc, None)
if irc is not None:
irc.error(_('My connection is restricted, I can\'t change nicks.'))
else:
self.log.debug('Got 484 without Admin.nick being called.')
def do433(self, irc, msg):
irc = self.pendingNickChanges.get(irc, None)
if irc is not None:
irc.error(_('Someone else is already using that nick.'))
else:
self.log.debug('Got 433 without Admin.nick being called.')
def do435(self, irc, msg):
irc = self.pendingNickChanges.get(irc, None)
if irc is not None:
irc.error(_('I can\'t change nick, I\'m currently banned in %s.') %
msg.args[2])
else:
self.log.debug('Got 435 without Admin.nick being called.')
def do438(self, irc, msg):
irc = self.pendingNickChanges.get(irc, None)
if irc is not None:
irc.error(format(_('I can\'t change nicks, the server said %q.'),
msg.args[2]), private=True)
else:
self.log.debug('Got 438 without Admin.nick being called.')
def doNick(self, irc, msg):
if msg.nick == irc.nick or msg.args[0] == irc.nick:
try:
del self.pendingNickChanges[irc]
except KeyError:
self.log.debug('Got NICK without Admin.nick being called.')
@internationalizeDocstring
def nick(self, irc, msg, args, nick, network):
"""[<nick>] [<network>]
Changes the bot's nick to <nick>. If no nick is given, returns the
bot's current nick.
"""
network = network or irc.network
if nick:
group = getattr(conf.supybot.networks, network)
group.nick.setValue(nick)
irc.queueMsg(ircmsgs.nick(nick))
self.pendingNickChanges[irc.getRealIrc()] = irc
else:
irc.reply(irc.nick)
nick = wrap(nick, [additional('nick'), additional('something')])
class capability(callbacks.Commands):
@internationalizeDocstring
def add(self, irc, msg, args, user, capability):
"""<name|hostmask> <capability>
Gives the user specified by <name> (or the user to whom <hostmask>
currently maps) the specified capability <capability>
"""
# Ok, the concepts that are important with capabilities:
#
### 1) No user should be able to elevate their privilege to owner.
### 2) Admin users are *not* superior to #channel.ops, and don't
### have God-like powers over channels.
### 3) We assume that Admin users are two things: non-malicious and
### and greedy for power. So they'll try to elevate their
### privilege to owner, but they won't try to crash the bot for
### no reason.
# Thus, the owner capability can't be given in the bot. Admin
# users can only give out capabilities they have themselves (which
# will depend on supybot.capabilities and its child default) but
# generally means they can't mess with channel capabilities.
if ircutils.strEqual(capability, 'owner'):
irc.error(_('The "owner" capability can\'t be added in the '
'bot. Use the supybot-adduser program (or edit the '
'users.conf file yourself) to add an owner '
'capability.'))
return
if ircdb.isAntiCapability(capability) or \
ircdb.checkCapability(msg.prefix, capability):
user.addCapability(capability)
ircdb.users.setUser(user)
irc.replySuccess()
else:
irc.error(_('You can\'t add capabilities you don\'t have.'))
add = wrap(add, ['otherUser', 'lowered'])
@internationalizeDocstring
def remove(self, irc, msg, args, user, capability):
"""<name|hostmask> <capability>
Takes from the user specified by <name> (or the user to whom
<hostmask> currently maps) the specified capability <capability>
"""
if ircdb.checkCapability(msg.prefix, capability) or \
ircdb.isAntiCapability(capability):
try:
user.removeCapability(capability)
ircdb.users.setUser(user)
irc.replySuccess()
except KeyError:
irc.error(_('That user doesn\'t have that capability.'))
else:
s = _('You can\'t remove capabilities you don\'t have.')
irc.error(s)
remove = wrap(remove, ['otherUser','lowered'])
class ignore(callbacks.Commands):
@internationalizeDocstring
def add(self, irc, msg, args, hostmask, expires):
"""<hostmask|nick> [<expires>]
This will set a persistent ignore on <hostmask> or the hostmask
currently associated with <nick>. <expires> is an optional argument
specifying when (in "seconds from now") the ignore will expire; if
it isn't given, the ignore will never automatically expire.
"""
ircdb.ignores.add(hostmask, expires)
irc.replySuccess()
add = wrap(add, ['hostmask', additional('expiry', 0)])
@internationalizeDocstring
def remove(self, irc, msg, args, hostmask):
"""<hostmask|nick>
This will remove the persistent ignore on <hostmask> or the
hostmask currently associated with <nick>.
"""
try:
ircdb.ignores.remove(hostmask)
irc.replySuccess()
except KeyError:
irc.error(_('%s wasn\'t in the ignores database.') % hostmask)
remove = wrap(remove, ['hostmask'])
@internationalizeDocstring
def list(self, irc, msg, args):
"""takes no arguments
Lists the hostmasks that the bot is ignoring.
"""
# XXX Add the expirations.
if ircdb.ignores.hostmasks:
irc.reply(format('%L', (list(map(repr,ircdb.ignores.hostmasks)))))
else:
irc.reply(_('I\'m not currently globally ignoring anyone.'))
list = wrap(list)
def clearq(self, irc, msg, args):
"""takes no arguments
Clears the current send queue for this network.
"""
irc.queue.reset()
irc.replySuccess()
clearq = wrap(clearq)
def acmd(self, irc, msg, args, commandAndArgs):
"""<command> [<arg> ...]
Perform <command> (with associated <arg>s on all channels on current network."""
for channel in irc.state.channels:
msg = ircmsgs.IrcMsg(msg=msg, args=(channel,) + msg.args[1:])
self.Proxy(irc.getRealIrc(), msg, commandAndArgs)
acmd = wrap(acmd, ['admin', many('something')])
Class = Admin
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,140 +0,0 @@
###
# Copyright (c) 2002-2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
from supybot.test import *
class AdminTestCase(PluginTestCase):
plugins = ('Admin', 'Utilities')
def testChannels(self):
def getAfterJoinMessages():
m = self.irc.takeMsg()
self.assertEqual(m.command, 'MODE')
m = self.irc.takeMsg()
self.assertEqual(m.command, 'MODE')
m = self.irc.takeMsg()
self.assertEqual(m.command, 'WHO')
self.assertRegexp('channels', 'not.*in any')
self.irc.feedMsg(ircmsgs.join('#foo', prefix=self.prefix))
getAfterJoinMessages()
self.assertRegexp('channels', '#foo')
self.irc.feedMsg(ircmsgs.join('#bar', prefix=self.prefix))
getAfterJoinMessages()
self.assertRegexp('channels', '#bar and #foo')
self.irc.feedMsg(ircmsgs.join('#Baz', prefix=self.prefix))
getAfterJoinMessages()
self.assertRegexp('channels', '#bar, #Baz, and #foo')
def testIgnoreAddRemove(self):
self.assertNotError('admin ignore add foo!bar@baz')
self.assertError('admin ignore add alsdkfjlasd')
self.assertNotError('admin ignore remove foo!bar@baz')
self.assertError('admin ignore remove foo!bar@baz')
def testIgnoreList(self):
self.assertNotError('admin ignore list')
self.assertNotError('admin ignore add foo!bar@baz')
self.assertNotError('admin ignore list')
self.assertNotError('admin ignore add foo!bar@baz')
self.assertRegexp('admin ignore list', 'foo')
def testCapabilityAdd(self):
self.assertError('capability add foo bar')
u = ircdb.users.newUser()
u.name = 'foo'
ircdb.users.setUser(u)
self.assertNotError('capability add foo bar')
self.assertError('addcapability foo baz')
self.assertIn('bar', u.capabilities)
ircdb.users.delUser(u.id)
def testCapabilityRemove(self):
self.assertError('capability remove foo bar')
u = ircdb.users.newUser()
u.name = 'foo'
ircdb.users.setUser(u)
self.assertNotError('capability add foo bar')
self.assertIn('bar', u.capabilities)
self.assertError('removecapability foo bar')
self.assertNotError('capability remove foo bar')
self.assertNotIn('bar', u.capabilities)
ircdb.users.delUser(u.id)
def testJoin(self):
m = self.getMsg('join #foo')
self.assertEqual(m.command, 'JOIN')
self.assertEqual(m.args[0], '#foo')
m = self.getMsg('join #foo key')
self.assertEqual(m.command, 'JOIN')
self.assertEqual(m.args[0], '#foo')
self.assertEqual(m.args[1], 'key')
def testNick(self):
try:
m = self.getMsg('nick foobar')
self.assertEqual(m.command, 'NICK')
self.assertEqual(m.args[0], 'foobar')
finally:
conf.supybot.networks.test.nick.setValue('')
def testAddCapabilityOwner(self):
self.assertError('admin capability add %s owner' % self.nick)
def testJoinOnOwnerInvite(self):
self.irc.feedMsg(ircmsgs.invite(conf.supybot.nick(), '#foo', prefix=self.prefix))
m = self.getMsg(' ')
self.assertEqual(m.command, 'JOIN')
self.assertEqual(m.args[0], '#foo')
def testNoJoinOnUnprivilegedInvite(self):
try:
world.testing = False
for channel in '#foo', '#foo\u0009':
self.irc.feedMsg(ircmsgs.invite(conf.supybot.nick(), channel, prefix='foo!bar@baz'))
self.assertResponse('somecommand',
'Error: "somecommand" is not a valid command.')
finally:
world.testing = True
def testAcmd(self):
self.irc.feedMsg(ircmsgs.join('#foo', prefix=self.prefix))
self.irc.feedMsg(ircmsgs.join('#bar', prefix=self.prefix))
while self.irc.takeMsg():
pass
msgs = []
msg = self.getMsg('acmd echo hi $channel')
while msg:
msgs.append(msg)
msg = self.irc.takeMsg()
self.assertCountEqual(
[(msg.command,) + msg.args for msg in msgs],
[("PRIVMSG", "#foo", "hi #foo"), ("PRIVMSG", "#bar", "hi #bar")])
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,157 +0,0 @@
.. _plugin-Aka:
Documentation for the Aka plugin for Supybot
============================================
Purpose
-------
This plugin allows the user to create various aliases (known as "Akas", since
Alias is the name of another plugin Aka is based on) to other commands or
combinations of other commands (via nested commands).
Usage
-----
This plugin allows users to define aliases to commands and combinations
of commands (via nesting).
Importing from Alias
^^^^^^^^^^^^^^^^^^^^
Add an aka, Alias, which eases the transitioning to Aka from Alias.
First we will load Alias and Aka::
<jamessan> @load Alias
<bot> jamessan: The operation succeeded.
<jamessan> @load Aka
<bot> jamessan: The operation succeeded.
Then we import the Alias database to Aka in case it exists and unload
Alias::
<jamessan> @importaliasdatabase
<bot> jamessan: The operation succeeded.
<jamessan> @unload Alias
<bot> jamessan: The operation succeeded.
And now we will finally add the Aka ``alias`` itself::
<jamessan> @aka add "alias" "aka $1 $*"
<bot> jamessan: The operation succeeded.
Now you can use Aka as you used Alias before.
Trout
^^^^^
Add an aka, ``trout``, which expects a word as an argument::
<jamessan> @aka add trout "reply action slaps $1 with a large trout"
<bot> jamessan: The operation succeeded.
<jamessan> @trout me
* bot slaps me with a large trout
This ``trout`` aka requires the plugin ``Reply`` to be loaded since it
provides the ``action`` command.
Random percentage
^^^^^^^^^^^^^^^^^
Add an aka, ``randpercent``, which returns a random percentage value::
@aka add randpercent "squish [dice 1d100]%"
This requires the ``Filter`` and ``Games`` plugins to be loaded.
Note that nested commands in an alias should be quoted, or they will only
run once when you create the alias, and not each time the alias is
called. (In this case, not quoting the nested command would mean that
``@randpercent`` always responds with the same value!)
.. _commands-Aka:
Commands
--------
.. _command-aka-add:
add [--channel <#channel>] <name> <command>
Defines an alias <name> that executes <command>. The <command> should be in the standard "command argument [nestedcommand argument]" arguments to the alias; they'll be filled with the first, second, etc. arguments. $1, $2, etc. can be used for required arguments. @1, @2, etc. can be used for optional arguments. $* simply means "all arguments that have not replaced $1, $2, etc.", ie. it will also include optional arguments.
.. _command-aka-remove:
remove [--channel <#channel>] <name>
Removes the given alias, if unlocked.
.. _command-aka-lock:
lock [--channel <#channel>] <alias>
Locks an alias so that no one else can change it.
.. _command-aka-unlock:
unlock [--channel <#channel>] <alias>
Unlocks an alias so that people can define new aliases over it.
.. _command-aka-importaliasdatabase:
importaliasdatabase takes no arguments
Imports the Alias database into Aka's, and clean the former.
.. _command-aka-show:
show [--channel <#channel>] <alias>
This command shows the content of an Aka.
.. _command-aka-list:
list [--channel <#channel>] [--keys] [--unlocked|--locked]
Lists all Akas defined for <channel>. If <channel> is not specified, lists all global Akas. If --keys is given, lists only the Aka names and not their commands.
.. _command-aka-set:
set [--channel <#channel>] <name> <command>
Overwrites an existing alias <name> to execute <command> instead. The <command> should be in the standard "command argument [nestedcommand argument]" arguments to the alias; they'll be filled with the first, second, etc. arguments. $1, $2, etc. can be used for required arguments. @1, @2, etc. can be used for optional arguments. $* simply means "all arguments that have not replaced $1, $2, etc.", ie. it will also include optional arguments.
.. _command-aka-search:
search [--channel <#channel>] <query>
Searches Akas defined for <channel>. If <channel> is not specified, searches all global Akas.
.. _conf-Aka:
Configuration
-------------
.. _conf-supybot.plugins.Aka.maximumWordsInName:
supybot.plugins.Aka.maximumWordsInName
This config variable defaults to "5", is not network-specific, and is not channel-specific.
The maximum number of words allowed in a command name. Setting this to an high value may slow down your bot on long commands.
.. _conf-supybot.plugins.Aka.public:
supybot.plugins.Aka.public
This config variable defaults to "True", is not network-specific, and is not channel-specific.
Determines whether this plugin is publicly visible.
.. _conf-supybot.plugins.Aka.web:
supybot.plugins.Aka.web
This is a group of:
.. _conf-supybot.plugins.Aka.web.enable:
supybot.plugins.Aka.web.enable
This config variable defaults to "False", is not network-specific, and is not channel-specific.
Determines whether the Akas will be browsable through the HTTP server.

View File

@ -1,70 +0,0 @@
###
# Copyright (c) 2013-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
"""
This plugin allows the user to create various aliases (known as "Akas", since
Alias is the name of another plugin Aka is based on) to other commands or
combinations of other commands (via nested commands).
"""
import supybot
import supybot.world as world
# Use this for the version of this plugin. You may wish to put a CVS keyword
# in here if you're keeping the plugin in CVS or some similar system.
__version__ = ""
__author__ = supybot.authors.progval
__maintainer__ = supybot.authors.limnoria_core
# This is a dictionary mapping supybot.Author instances to lists of
# contributions.
__contributors__ = {}
# This is a url where the most recent plugin package can be downloaded.
__url__ = '' # 'http://supybot.com/Members/yourname/Aka/download'
from . import config
from . import plugin
from importlib import reload
# In case we're being reloaded.
reload(config)
reload(plugin)
# Add more reloads here if you add third-party modules and want them to be
# reloaded when this plugin is reloaded. Don't forget to import them as well!
if world.testing:
from . import test
Class = plugin.Class
configure = config.configure
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:

View File

@ -1,64 +0,0 @@
###
# Copyright (c) 2013-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import supybot.conf as conf
import supybot.registry as registry
try:
from supybot.i18n import PluginInternationalization
_ = PluginInternationalization('Aka')
except:
# Placeholder that allows to run the plugin on a bot
# without the i18n module
_ = lambda x:x
def configure(advanced):
# This will be called by supybot to configure this module. advanced is
# a bool that specifies whether the user identified themself as an advanced
# user or not. You should effect your configuration by manipulating the
# registry as appropriate.
from supybot.questions import expect, anything, something, yn
conf.registerPlugin('Aka', True)
Aka = conf.registerPlugin('Aka')
# This is where your configuration variables (if any) should go. For example:
# conf.registerGlobalValue(Aka, 'someConfigVariableName',
# registry.Boolean(False, _("""Help for someConfigVariableName.""")))
conf.registerGlobalValue(Aka, 'maximumWordsInName',
registry.Integer(5, _("""The maximum number of words allowed in a
command name. Setting this to an high value may slow down your bot
on long commands.""")))
conf.registerGroup(Aka, 'web')
conf.registerGlobalValue(Aka.web, 'enable',
registry.Boolean(False, _("""Determines whether the Akas will be
browsable through the HTTP server.""")))
# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:

View File

@ -1 +0,0 @@
# Stub so local is a module, used for third-party modules

View File

@ -1,376 +0,0 @@
# Aka plugin for Limnoria
# Copyright (C) 2014 Limnoria
# Mikaela Suomalainen <mikaela.suomalainen@outlook.com>, 2014.
#
msgid ""
msgstr ""
"Project-Id-Version: Aka plugin for Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2014-12-20 13:57+0200\n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: \n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 1.6.10\n"
#: config.py:55
msgid ""
"The maximum number of words allowed in a\n"
" command name. Setting this to an high value may slow down your bot\n"
" on long commands."
msgstr ""
"Komennon nimessä sallittujen merkkien enimmäismäärä.\n"
" Korkean arvon asettaminen tähän voi hidastaa bottiasi pitkien komentojen "
"kanssa."
#: config.py:61
msgid ""
"Determines whether the Akas will be\n"
" browsable through the HTTP server."
msgstr ""
#: plugin.py:141 plugin.py:274 plugin.py:732
msgid "This Aka already exists."
msgstr "Tämä Aka on jo olemassa."
#: plugin.py:170 plugin.py:182 plugin.py:196 plugin.py:301 plugin.py:318
#: plugin.py:335 plugin.py:912
msgid "This Aka does not exist."
msgstr "Tätä Akaa ei ole olemassa."
#: plugin.py:303
msgid "This Aka is already locked."
msgstr "Tämä Aka on jo lukittu."
#: plugin.py:320
msgid "This Aka is already unlocked."
msgstr "Tämä Aka on jo avattu."
#: plugin.py:465
#, fuzzy
msgid "By %s at %s"
msgstr "Lukinnut %s aikaan %s"
#: plugin.py:501
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
"\n"
" Importing from Alias\n"
" ^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" Add an aka, Alias, which eases the transitioning to Aka from Alias.\n"
"\n"
" First we will load Alias and Aka::\n"
"\n"
" <jamessan> @load Alias\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @load Aka\n"
" <bot> jamessan: The operation succeeded.\n"
"\n"
" Then we import the Alias database to Aka in case it exists and unload\n"
" Alias::\n"
"\n"
" <jamessan> @importaliasdatabase\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @unload Alias\n"
" <bot> jamessan: The operation succeeded.\n"
"\n"
" And now we will finally add the Aka ``alias`` itself::\n"
"\n"
" <jamessan> @aka add \"alias\" \"aka $1 $*\"\n"
" <bot> jamessan: The operation succeeded.\n"
"\n"
" Now you can use Aka as you used Alias before.\n"
"\n"
" Trout\n"
" ^^^^^\n"
"\n"
" Add an aka, trout, which expects a word as an argument::\n"
"\n"
" <jamessan> @aka add trout \"reply action slaps $1 with a large trout"
"\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" This ``trout`` aka requires the plugin ``Reply`` to be loaded since it\n"
" provides the ``action`` command.\n"
"\n"
" LastFM\n"
" ^^^^^^\n"
"\n"
" Add an aka, ``lastfm``, which expects a last.fm username and replies "
"with\n"
" their most recently played item::\n"
"\n"
" @aka add lastfm \"rss [format concat http://ws.audioscrobbler."
"com/1.0/user/ [format concat [web urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" This ``lastfm`` aka requires the following plugins to be loaded: "
"``RSS``,\n"
" ``Format`` and ``Web``.\n"
"\n"
" ``RSS`` provides ``rss``, ``Format`` provides ``concat`` and ``Web`` "
"provides\n"
" ``urlquote``.\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and ``@lastfm`` would "
"always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:699
msgid "You've attempted more nesting than is currently allowed on this bot."
msgstr ""
"Olet yrittänyt sisällyttää enemmän komentoja, kuin tässä botti sallii juuri "
"nyt."
#: plugin.py:703
msgid " at least"
msgstr "ainakin"
#: plugin.py:712
msgid "Locked by %s at %s"
msgstr "Lukinnut %s aikaan %s"
#: plugin.py:717
#, fuzzy
msgid ""
"<a global alias,%s %n>\n"
"\n"
"Alias for %q.%s"
msgstr ""
"<alias,%s %n>\n"
"\n"
"Alias komennolle %q.%s"
#: plugin.py:718 plugin.py:722
msgid "argument"
msgstr "parametri"
#: plugin.py:721
#, fuzzy
msgid ""
"<an alias on %s,%s %n>\n"
"\n"
"Alias for %q.%s"
msgstr ""
"<alias,%s %n>\n"
"\n"
"Alias komennolle %q.%s"
#: plugin.py:729
msgid "You can't overwrite commands in this plugin."
msgstr "Et voi ylikirjoittaa tämän lisä-osan komentoja."
#: plugin.py:734
msgid "This Aka has too many spaces in its name."
msgstr "Tämän Akan nimessä on liian monta välilyöntiä."
#: plugin.py:739
msgid "Can't mix $* and optional args (@1, etc.)"
msgstr ""
"$*:ä ja vapaaehtoisia parametrejä (@1, jne.) ei voida sekoittaa keskenään"
#: plugin.py:746
msgid "This Aka is locked."
msgstr "Tämä Aka on lukittu."
#: plugin.py:750
#, fuzzy
msgid ""
"[--channel <#channel>] <name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand "
"argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, "
"etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, "
"@2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" arguments that have not replaced $1, $2, etc.\", ie. it will also\n"
" include optional arguments.\n"
" "
msgstr ""
"[--channel <#kanava>] <nimi> <komento>\n"
"\n"
"Määrittää aliaksen <nimi>, joka suorittaa <komennon>. <Komennon>\n"
" pitäisi olla tavallisessa muodossa \"komento parametri [sisällytettykomento "
"parametri]\"\n"
" parametreinä aliakselle; ne täytetään ensimmäisenä, toisena, jne.\n"
" parametreinä. $1, $2, jne. voidaan käyttää vaadittuina parametreinä. @1, "
"@2,\n"
" jne. voidaan käyttää vapaaehtoisina parametreinä. $* tarkoittaa "
"yksinkertaisesti \"kaikki\n"
" jotka eivät ole korvanneet $1, $2, jne.\", esim. se sisältää vapaa-ehtoiset "
"parametrit.\n"
" "
#: plugin.py:764 plugin.py:796 plugin.py:827 plugin.py:859 plugin.py:882
#: plugin.py:905 plugin.py:951 plugin.py:994
msgid "%r is not a valid channel."
msgstr "%r ei ole kelvollinen kanava."
#: plugin.py:782
#, fuzzy
msgid ""
"[--channel <#channel>] <name> <command>\n"
"\n"
" Overwrites an existing alias <name> to execute <command> instead. "
"The\n"
" <command> should be in the standard \"command argument "
"[nestedcommand\n"
" argument]\" arguments to the alias; they'll be filled with the "
"first,\n"
" second, etc. arguments. $1, $2, etc. can be used for required\n"
" arguments. @1, @2, etc. can be used for optional arguments. $* "
"simply\n"
" means \"all arguments that have not replaced $1, $2, etc.\", ie. it "
"will\n"
" also include optional arguments.\n"
" "
msgstr ""
"[--kanava <#kanava>] <nimi> <komento>\n"
" Ylikirjoittaa olemassa olevan aliaksen <nimi> suorittamaan <komennon> "
"sensijaan. <Komennon>\n"
" pitäisi olla standardissa \"komento parametri [sisäkkäinen komento\" "
"parametreinä aliakselle; ne täytetään\n"
" ensimmäisillä, toisilla jne. parametreillä. $1, $2, jne. voidaan käyttää "
"vaadittuihin parametreihin. $*\n"
" yksinkertaisesti tarkoittaa \"kaikki parametrin, joita ei ole korvattu $1, "
"$2 jne.\", esimerkiksi. se sisällyttää\n"
" myös kaikki vapaaehtoiset parametrit."
#: plugin.py:819
msgid ""
"[--channel <#channel>] <name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
"[--channel <#kanava>] <nimi>\n"
"\n"
" Poistaa annetun aliaksen, ellei se ole lukittu.\n"
" "
#: plugin.py:841
msgid ""
"Check if the user has any of the required capabilities to manage\n"
" the regexp database."
msgstr ""
"Tarkistaa onko käyttäjällä vaadittu valtuus säännöllisten lausekkeiden\n"
" tietokannan hallintaan."
#: plugin.py:851
msgid ""
"[--channel <#channel>] <alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
"[--channel <#kanava>] <alias>\n"
"\n"
" Lukitsee aliaksen estäen muita muokkaamasta sitä.\n"
" "
#: plugin.py:874
msgid ""
"[--channel <#channel>] <alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
"[--channel <#kanava>] <alias>\n"
"\n"
" Avaa aliaksen, jotta kaikki voivat määrittää uusia aliaksia sen päälle.\n"
" "
#: plugin.py:897
msgid ""
"[--channel <#channel>] <alias>\n"
"\n"
" This command shows the content of an Aka.\n"
" "
msgstr ""
"<komento> <#kanava> <alias>\n"
"\n"
" Tämä komento näyttää Akan sisällön."
#: plugin.py:917
msgid ""
"takes no arguments\n"
"\n"
" Imports the Alias database into Aka's, and clean the former."
msgstr ""
"ei ota parametrejä\n"
"\n"
" Tuo Aliaksen tietokannan Akaan ja tyhjentää aiemman."
#: plugin.py:922
msgid "Alias plugin is not loaded."
msgstr "Alias lisä-osa ei ole ladattu."
#: plugin.py:933
msgid "Error occured when importing the %n: %L"
msgstr "Virhe komennon %n tuomisessa: %L"
#: plugin.py:941
msgid ""
"[--channel <#channel>] [--keys] [--unlocked|--locked]\n"
"\n"
" Lists all Akas defined for <channel>. If <channel> is not "
"specified,\n"
" lists all global Akas. If --keys is given, lists only the Aka names\n"
" and not their commands."
msgstr ""
#: plugin.py:960
msgid "--locked and --unlocked are incompatible options."
msgstr ""
#: plugin.py:980
msgid "No Akas found."
msgstr ""
#: plugin.py:985
msgid ""
"[--channel <#channel>] <query>\n"
"\n"
" Searches Akas defined for <channel>. If <channel> is not specified,\n"
" searches all global Akas."
msgstr ""
#: plugin.py:1004
msgid "No matching Akas were found."
msgstr ""
#~ msgid ""
#~ "Aka is the improved version of the Alias plugin. It stores akas outside\n"
#~ " of the bot.conf, which doesn't have risk of corrupting the bot.conf "
#~ "file\n"
#~ " (this often happens when there are Unicode issues). Aka also\n"
#~ " introduces multi-worded akas."
#~ msgstr ""
#~ "Aka on paranneltu versio Alias pluginista. Se tallentaa akat bot.conf-"
#~ "tiedoston ulkopuolelle, jollla ei ole\n"
#~ " riskiä korruptoida bot.conf tiedostoa (joka tapahtuu usein Unicode-"
#~ "ongelmien kanssa). Aka\n"
#~ " tukee myös useamman akan pituisia akoja."
#~ msgid "There can be only one $* in an alias."
#~ msgstr "Aliaksessa voi olla vain yksi $*."
#~ msgid ""
#~ "Add the help for 'plugin help Aka' here\n"
#~ " This should describe *how* to use this plugin."
#~ msgstr ""
#~ "Lisää ohje komentoa 'plugin help Aka' varten tähän.\n"
#~ " Tämän pitäisi kuvata *kuinka* tätä lisä-osaa käytetään."

View File

@ -1,289 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: config.py:55
msgid ""
"The maximum number of words allowed in a\n"
" command name. Setting this to an high value may slow down your bot\n"
" on long commands."
msgstr ""
#: config.py:61
msgid ""
"Determines whether the Akas will be\n"
" browsable through the HTTP server."
msgstr ""
#: plugin.py:141 plugin.py:274 plugin.py:732
msgid "This Aka already exists."
msgstr ""
#: plugin.py:170 plugin.py:182 plugin.py:196 plugin.py:301 plugin.py:318
#: plugin.py:335 plugin.py:912
msgid "This Aka does not exist."
msgstr ""
#: plugin.py:303
msgid "This Aka is already locked."
msgstr ""
#: plugin.py:320
msgid "This Aka is already unlocked."
msgstr ""
#: plugin.py:465
msgid "By %s at %s"
msgstr ""
#: plugin.py:501
#, docstring
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
"\n"
" Importing from Alias\n"
" ^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" Add an aka, Alias, which eases the transitioning to Aka from Alias.\n"
"\n"
" First we will load Alias and Aka::\n"
"\n"
" <jamessan> @load Alias\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @load Aka\n"
" <bot> jamessan: The operation succeeded.\n"
"\n"
" Then we import the Alias database to Aka in case it exists and unload\n"
" Alias::\n"
"\n"
" <jamessan> @importaliasdatabase\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @unload Alias\n"
" <bot> jamessan: The operation succeeded.\n"
"\n"
" And now we will finally add the Aka ``alias`` itself::\n"
"\n"
" <jamessan> @aka add \"alias\" \"aka $1 $*\"\n"
" <bot> jamessan: The operation succeeded.\n"
"\n"
" Now you can use Aka as you used Alias before.\n"
"\n"
" Trout\n"
" ^^^^^\n"
"\n"
" Add an aka, trout, which expects a word as an argument::\n"
"\n"
" <jamessan> @aka add trout \"reply action slaps $1 with a large trout\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" This ``trout`` aka requires the plugin ``Reply`` to be loaded since it\n"
" provides the ``action`` command.\n"
"\n"
" LastFM\n"
" ^^^^^^\n"
"\n"
" Add an aka, ``lastfm``, which expects a last.fm username and replies with\n"
" their most recently played item::\n"
"\n"
" @aka add lastfm \"rss [format concat http://ws.audioscrobbler.com/1.0/user/ [format concat [web urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" This ``lastfm`` aka requires the following plugins to be loaded: ``RSS``,\n"
" ``Format`` and ``Web``.\n"
"\n"
" ``RSS`` provides ``rss``, ``Format`` provides ``concat`` and ``Web`` provides\n"
" ``urlquote``.\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and ``@lastfm`` would always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:699
msgid "You've attempted more nesting than is currently allowed on this bot."
msgstr ""
#: plugin.py:703
msgid " at least"
msgstr ""
#: plugin.py:712
msgid "Locked by %s at %s"
msgstr ""
#: plugin.py:717
msgid ""
"<a global alias,%s %n>\n"
"\n"
"Alias for %q.%s"
msgstr ""
#: plugin.py:718 plugin.py:722
msgid "argument"
msgstr ""
#: plugin.py:721
msgid ""
"<an alias on %s,%s %n>\n"
"\n"
"Alias for %q.%s"
msgstr ""
#: plugin.py:729
msgid "You can't overwrite commands in this plugin."
msgstr ""
#: plugin.py:734
msgid "This Aka has too many spaces in its name."
msgstr ""
#: plugin.py:739
msgid "Can't mix $* and optional args (@1, etc.)"
msgstr ""
#: plugin.py:746
msgid "This Aka is locked."
msgstr ""
#: plugin.py:750
#, docstring
msgid ""
"[--channel <#channel>] <name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, @2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" arguments that have not replaced $1, $2, etc.\", ie. it will also\n"
" include optional arguments.\n"
" "
msgstr ""
#: plugin.py:764 plugin.py:796 plugin.py:827 plugin.py:859 plugin.py:882
#: plugin.py:905 plugin.py:951 plugin.py:994
msgid "%r is not a valid channel."
msgstr ""
#: plugin.py:782
#, docstring
msgid ""
"[--channel <#channel>] <name> <command>\n"
"\n"
" Overwrites an existing alias <name> to execute <command> instead. The\n"
" <command> should be in the standard \"command argument [nestedcommand\n"
" argument]\" arguments to the alias; they'll be filled with the first,\n"
" second, etc. arguments. $1, $2, etc. can be used for required\n"
" arguments. @1, @2, etc. can be used for optional arguments. $* simply\n"
" means \"all arguments that have not replaced $1, $2, etc.\", ie. it will\n"
" also include optional arguments.\n"
" "
msgstr ""
#: plugin.py:819
#, docstring
msgid ""
"[--channel <#channel>] <name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
#: plugin.py:841
#, docstring
msgid ""
"Check if the user has any of the required capabilities to manage\n"
" the regexp database."
msgstr ""
#: plugin.py:851
#, docstring
msgid ""
"[--channel <#channel>] <alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
#: plugin.py:874
#, docstring
msgid ""
"[--channel <#channel>] <alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
#: plugin.py:897
#, docstring
msgid ""
"[--channel <#channel>] <alias>\n"
"\n"
" This command shows the content of an Aka.\n"
" "
msgstr ""
#: plugin.py:917
#, docstring
msgid ""
"takes no arguments\n"
"\n"
" Imports the Alias database into Aka's, and clean the former."
msgstr ""
#: plugin.py:922
msgid "Alias plugin is not loaded."
msgstr ""
#: plugin.py:933
msgid "Error occured when importing the %n: %L"
msgstr ""
#: plugin.py:941
#, docstring
msgid ""
"[--channel <#channel>] [--keys] [--unlocked|--locked]\n"
"\n"
" Lists all Akas defined for <channel>. If <channel> is not specified,\n"
" lists all global Akas. If --keys is given, lists only the Aka names\n"
" and not their commands."
msgstr ""
#: plugin.py:960
msgid "--locked and --unlocked are incompatible options."
msgstr ""
#: plugin.py:980
msgid "No Akas found."
msgstr ""
#: plugin.py:985
#, docstring
msgid ""
"[--channel <#channel>] <query>\n"
"\n"
" Searches Akas defined for <channel>. If <channel> is not specified,\n"
" searches all global Akas."
msgstr ""
#: plugin.py:1004
msgid "No matching Akas were found."
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@ -1,345 +0,0 @@
# -*- coding: utf8 -*-
###
# Copyright (c) 2002-2004, Jeremiah Fincher
# Copyright (c) 2013-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
from supybot.test import *
import supybot.conf as conf
import supybot.httpserver as httpserver
import supybot.plugin as plugin
import supybot.registry as registry
from supybot.utils.minisix import u
from . import plugin as Aka
class FunctionsTest(SupyTestCase):
def testFindBiggestDollar(self):
self.assertEqual(Aka.findBiggestDollar(''), 0)
self.assertEqual(Aka.findBiggestDollar('foo'), 0)
self.assertEqual(Aka.findBiggestDollar('$0'), 0)
self.assertEqual(Aka.findBiggestDollar('$1'), 1)
self.assertEqual(Aka.findBiggestDollar('$2'), 2)
self.assertEqual(Aka.findBiggestDollar('$2 $10'), 10)
self.assertEqual(Aka.findBiggestDollar('$3'), 3)
self.assertEqual(Aka.findBiggestDollar('$3 $2 $1'), 3)
self.assertEqual(Aka.findBiggestDollar('foo bar $1'), 1)
self.assertEqual(Aka.findBiggestDollar('foo $2 $1'), 2)
self.assertEqual(Aka.findBiggestDollar('foo $0 $1'), 1)
self.assertEqual(Aka.findBiggestDollar('foo $1 $3'), 3)
self.assertEqual(Aka.findBiggestDollar('$10 bar $1'), 10)
class AkaChannelTestCase(ChannelPluginTestCase):
plugins = ('Aka', 'Conditional', 'Filter', 'Math', 'Utilities',
'Format', 'Reply', 'String')
def testHistsearch(self):
self.assertNotError(
r'aka add histsearch "last --from [cif true '
r'\"echo test\" \"echo test\"] '
r'--regexp [concat \"m/$1/\" [re s/g// \"@2\"]]"')
self.assertResponse('echo foo', 'foo')
self.assertResponse('histsearch .*foo.*', '@echo foo')
def testDoesNotOverwriteCommands(self):
# We don't have dispatcher commands anymore
#self.assertError('aka add aka "echo foo bar baz"')
self.assertError('aka add add "echo foo bar baz"')
self.assertError('aka add remove "echo foo bar baz"')
self.assertError('aka add lock "echo foo bar baz"')
self.assertError('aka add unlock "echo foo bar baz"')
def testAkaHelp(self):
self.assertNotError(r'aka add slashdot "foo \"bar\" baz"')
self.assertRegexp('help slashdot', r'Alias for "foo \\"bar\\" baz".')
self.assertNotError('aka add nonascii echo éé')
self.assertRegexp('help nonascii', r'Alias for "echo éé".')
self.assertNotError('aka remove slashdot')
self.assertNotError('aka add --channel %s slashdot foo' % self.channel)
self.assertRegexp('help aka slashdot', "an alias on %s.*Alias for .*foo"
% self.channel)
self.assertNotError('aka remove --channel %s slashdot' % self.channel)
def testShow(self):
self.assertNotError('aka add foo bar')
self.assertResponse('show foo', 'bar $*')
self.assertNotError('aka add "foo bar" baz')
self.assertResponse('show "foo bar"', 'baz $*')
def testRemove(self):
self.assertNotError('aka add foo echo bar')
self.assertResponse('foo', 'bar')
self.assertNotError('aka remove foo')
self.assertError('foo')
def testDollars(self):
self.assertNotError('aka add rot26 "rot13 [rot13 $1]"')
self.assertResponse('rot26 foobar', 'foobar')
def testMoreDollars(self):
self.assertNotError('aka add rev "echo $3 $2 $1"')
self.assertResponse('rev foo bar baz', 'baz bar foo')
def testAllArgs(self):
self.assertNotError('aka add swap "echo $2 $1 $*"')
self.assertResponse('swap 1 2 3 4 5', '2 1 3 4 5')
self.assertError('aka add foo "echo $1 @1 $*"')
self.assertNotError('aka add moo echo $1 $*')
self.assertError('moo')
self.assertResponse('moo foo', 'foo')
self.assertResponse('moo foo bar', 'foo bar')
self.assertNotError('aka add spam "echo [echo $*]"')
self.assertResponse('spam egg', 'egg')
self.assertResponse('spam egg bacon', 'egg bacon')
self.assertNotError('aka add doublespam "echo [echo $* $*]"')
self.assertResponse('doublespam egg', 'egg egg')
self.assertResponse('doublespam egg bacon', 'egg bacon egg bacon')
def testExpansionBomb(self):
self.assertNotError('aka add bomb "bomb $* $* $* $* $*"')
# if the mitigation doesn't work, this test will eat all memory on the
# system.
self.assertResponse('bomb foo', "Error: You've attempted more nesting "
"than is currently allowed on this bot.")
def testChannel(self):
self.assertNotError('aka add channel echo $channel')
self.assertResponse('aka channel', self.channel)
def testAddRemoveAka(self):
cb = self.irc.getCallback('Aka')
cb._add_aka('global', 'foobar', 'echo sbbone')
cb._db.lock_aka('global', 'foobar', 'evil_admin')
self.assertResponse('foobar', 'sbbone')
self.assertRegexp('aka list', 'foobar')
self.assertRaises(Aka.AkaError, cb._remove_aka, 'global', 'foobar')
cb._remove_aka('global', 'foobar', evenIfLocked=True)
self.assertNotRegexp('aka list', 'foobar')
self.assertError('foobar')
def testOptionalArgs(self):
self.assertNotError('aka add myrepr "repr @1"')
self.assertResponse('myrepr foo', '"foo"')
self.assertResponse('myrepr ""', '""')
def testRequiredAndOptional(self):
self.assertNotError('aka add reqopt "echo req=$1, opt=@1"')
self.assertResponse('reqopt foo bar', 'req=foo, opt=bar')
self.assertResponse('reqopt foo', 'req=foo, opt=')
def testNoExtraSpaces(self):
self.assertNotError('aka add foo "action takes $1\'s money"')
self.assertResponse('foo bar', '\x01ACTION takes bar\'s money\x01')
def testNoExtraQuotes(self):
self.assertNotError('aka add myre "echo s/$1/$2/g"')
self.assertResponse('myre foo bar', 's/foo/bar/g')
def testSimpleAkaWithoutArgsImpliesDollarStar(self):
self.assertNotError('aka add exo echo')
self.assertResponse('exo foo bar baz', 'foo bar baz')
def testChannelPriority(self):
self.assertNotError('aka add spam "echo foo"')
self.assertNotError('aka add --channel %s spam "echo bar"' %
self.channel)
self.assertResponse('spam', 'bar')
self.assertNotError('aka add --channel %s egg "echo baz"' %
self.channel)
self.assertNotError('aka add egg "echo qux"')
self.assertResponse('egg', 'baz')
def testComplicatedNames(self):
self.assertNotError(u('aka add café "echo coffee"'))
self.assertResponse(u('café'), 'coffee')
self.assertNotError('aka add "foo bar" "echo spam"')
self.assertResponse('foo bar', 'spam')
self.assertNotError('aka add "foo" "echo egg"')
self.assertResponse('foo', 'egg')
# You could expect 'spam' here, but in fact, this is dangerous.
# Just imagine this session:
# <evil_user> aka add "echo foo" quit
# <bot> The operation succeeded.
# ...
# <owner> echo foo
# * bot has quit
self.assertResponse('foo bar', 'egg')
def testNoOverride(self):
self.assertNotError('aka add "echo foo" "echo bar"')
self.assertResponse('echo foo', 'foo')
self.assertNotError('aka add foo "echo baz"')
self.assertNotError('aka add "foo bar" "echo qux"')
self.assertResponse('foo bar', 'baz')
def testRecursivity(self):
self.assertNotError('aka add fact '
r'"cif [nceq $1 0] \"echo 1\" '
r'\"calc $1 * [fact [calc $1 - 1]]\""')
self.assertResponse('fact 4', '24')
self.assertRegexp('fact 50', 'more nesting')
def testDollarStarNesting(self):
self.assertResponse('aka add alias aka $*', 'The operation succeeded.')
self.assertResponse('alias add a+ aka add $*', 'The operation succeeded.')
self.assertResponse('a+ spam echo egg', 'The operation succeeded.')
self.assertResponse('spam', 'egg')
def testIgnore(self):
self.assertResponse('aka add test ignore', 'The operation succeeded.')
self.assertNoResponse('test')
class AkaTestCase(PluginTestCase):
plugins = ('Aka', 'Alias', 'User', 'Utilities')
def testMaximumLength(self):
self.assertNotError('aka add "foo bar baz qux quux" "echo test"')
self.assertError('aka add "foo bar baz qux quux corge" "echo test"')
def testAkaLockedHelp(self):
self.assertNotError('register evil_admin foo')
self.assertNotError('aka add slashdot foo')
self.assertRegexp('help aka slashdot', "a global alias.*Alias for .*foo")
self.assertNotRegexp('help aka slashdot', 'Locked by')
self.assertNotError('aka lock slashdot')
self.assertRegexp('help aka slashdot', 'Locked by evil_admin')
self.assertNotError('aka unlock slashdot')
self.assertNotRegexp('help aka slashdot', 'Locked by')
def testAliasImport(self):
self.assertNotError('alias add foo "echo bar"')
self.assertNotError(u('alias add baz "echo café"'))
self.assertNotError('aka add qux "echo quux"')
self.assertResponse('alias foo', 'bar')
self.assertResponse('alias baz', 'café')
self.assertRegexp('aka foo', 'there is no command named')
self.assertResponse('aka qux', 'quux')
self.assertNotError('aka importaliasdatabase')
self.assertRegexp('alias foo', 'there is no command named')
self.assertResponse('aka foo', 'bar')
self.assertResponse('aka baz', 'café')
self.assertResponse('aka qux', 'quux')
self.assertNotError('alias add foo "echo test"')
self.assertNotError('alias add spam "echo egg"')
self.assertNotError('alias lock spam')
self.assertRegexp('aka importaliasdatabase',
r'the 1 following command: foo \(This Aka already exists.\)$')
self.assertResponse('aka foo', 'bar')
self.assertResponse('alias foo', 'test')
self.assertRegexp('alias spam', 'there is no command named')
self.assertResponse('aka spam', 'egg')
def testList(self):
self.assertNotError('aka add foo bar')
self.assertRegexp('aka list', r'foo.*?bar \$\*')
self.assertNotError('aka add "foo bar" baz')
self.assertRegexp('aka list', r'foo.*?bar \$\*.*?foo bar.*?baz \$\*')
def testListLockedUnlocked(self):
self.assertNotError('register tacocat hunter2')
self.assertNotError('aka add foo bar')
self.assertNotError('aka add abcd echo hi')
self.assertNotError('aka lock foo')
self.assertRegexp('aka list --locked', 'foo')
self.assertNotRegexp('aka list --locked', 'abcd')
self.assertNotRegexp('aka list --unlocked', 'foo')
self.assertRegexp('aka list --unlocked', 'abcd')
# Can't look up both.
self.assertError('aka list --locked --unlocked abcd')
def testSearch(self):
self.assertNotError('aka add foo bar')
self.assertNotError('aka add "many words" "much command"')
self.assertRegexp('aka search f', 'foo')
self.assertError('aka search abcdefghijklmnop')
self.assertRegexp('aka search many', 'many words')
# This should be case insensitive too.
self.assertRegexp('aka search MaNY', 'many words')
class AkaWebUITestCase(ChannelHTTPPluginTestCase):
plugins = ('Aka',)
config = {
'servers.http.keepAlive': True,
'plugins.Aka.web.enable': False,
}
def setUp(self):
super(ChannelHTTPPluginTestCase, self).setUp()
httpserver.startServer()
def tearDown(self):
httpserver.stopServer()
super(ChannelHTTPPluginTestCase, self).tearDown()
def testToggleWebEnable(self):
self.assertHTTPResponse('/aka/', 404)
self.assertNotError('config plugins.Aka.web.enable True')
self.assertHTTPResponse('/aka/', 200)
self.assertNotError('config plugins.Aka.web.enable False')
self.assertHTTPResponse('/aka/', 404)
def testGlobalPage(self):
self.assertNotError('config plugins.Aka.web.enable True')
self.assertNotError('aka add foo1 echo 1')
self.assertNotError('aka add --channel #foo foo2 echo 2')
self.assertNotError('aka add --channel #bar foo3 echo 3')
(respCode, body) = self.request('/aka/list/global')
self.assertEqual(respCode, 200)
self.assertIn(b'foo1', body)
self.assertNotIn(b'foo2', body)
self.assertNotIn(b'foo3', body)
def testChannelPage(self):
self.assertNotError('config plugins.Aka.web.enable True')
self.assertNotError('aka add foo1 echo 1')
self.assertNotError('aka add --channel #foo foo2 echo 2')
self.assertNotError('aka add --channel #bar foo3 echo 3')
(respCode, body) = self.request('/aka/list/%23foo')
self.assertEqual(respCode, 200)
self.assertIn(b'foo1', body)
self.assertIn(b'foo2', body)
self.assertNotIn(b'foo3', body)
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,101 +0,0 @@
.. _plugin-Alias:
Documentation for the Alias plugin for Supybot
==============================================
Purpose
-------
Allows aliases for other commands. NOTE THAT IT'S RECOMMENDED TO USE Aka
PLUGIN INSTEAD!
Usage
-----
This plugin allows users to define aliases to commands and combinations
of commands (via nesting).
This plugin is only kept for backward compatibility, you should use the
built-in Aka plugin instead (you can migrate your existing aliases using
the 'importaliasdatabase' command.
To add an alias, ``trout``, which expects a word as an argument::
<jamessan> @alias add trout "action slaps $1 with a large trout"
<bot> jamessan: The operation succeeded.
<jamessan> @trout me
* bot slaps me with a large trout
Add an alias, ``randpercent``, which returns a random percentage value::
@alias add randpercent "squish [dice 1d100]%"
This requires the ``Filter`` and ``Games`` plugins to be loaded.
Note that nested commands in an alias should be quoted, or they will only
run once when you create the alias, and not each time the alias is
called. (In this case, not quoting the nested command would mean that
``@randpercent`` always responds with the same value!)
.. _commands-Alias:
Commands
--------
.. _command-alias-add:
add <name> <command>
Defines an alias <name> that executes <command>. The <command> should be in the standard "command argument [nestedcommand argument]" arguments to the alias; they'll be filled with the first, second, etc. arguments. $1, $2, etc. can be used for required arguments. @1, @2, etc. can be used for optional arguments. $* simply means "all remaining arguments," and cannot be combined with optional arguments.
.. _command-alias-list:
list [--locked|--unlocked]
Lists alias names of a particular type, defaults to all aliases if no --locked or --unlocked option is given.
.. _command-alias-lock:
lock <alias>
Locks an alias so that no one else can change it.
.. _command-alias-remove:
remove <name>
Removes the given alias, if unlocked.
.. _command-alias-unlock:
unlock <alias>
Unlocks an alias so that people can define new aliases over it.
.. _conf-Alias:
Configuration
-------------
.. _conf-supybot.plugins.Alias.aliases:
supybot.plugins.Alias.aliases
This is a group of:
.. _conf-supybot.plugins.Alias.escapedaliases:
supybot.plugins.Alias.escapedaliases
This is a group of:
.. _conf-supybot.plugins.Alias.public:
supybot.plugins.Alias.public
This config variable defaults to "True", is not network-specific, and is not channel-specific.
Determines whether this plugin is publicly visible.
.. _conf-supybot.plugins.Alias.validName:
supybot.plugins.Alias.validName
This config variable defaults to "^[^\\x00-\\x20]+$", is not network-specific, and is not channel-specific.
Regex which alias names must match in order to be valid

View File

@ -1,65 +0,0 @@
###
# Copyright (c) 2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
"""
Allows aliases for other commands. NOTE THAT IT'S RECOMMENDED TO USE Aka
PLUGIN INSTEAD!
"""
import supybot
import supybot.world as world
# Use this for the version of this plugin. You may wish to put a CVS keyword
# in here if you're keeping the plugin in CVS or some similar system.
__version__ = ""
__author__ = supybot.authors.jemfinch
__maintainer__ = supybot.authors.limnoria_core
# This is a dictionary mapping supybot.Author instances to lists of
# contributions.
__contributors__ = {}
from . import config
from . import plugin
from importlib import reload
reload(plugin) # In case we're being reloaded.
# Add more reloads here if you add third-party modules and want them to be
# reloaded when this plugin is reloaded. Don't forget to import them as well!
from .plugin import findBiggestDollar, AliasError, escapeAlias, unescapeAlias # for the tests.
if world.testing:
from . import test
Class = plugin.Class
configure = config.configure
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,50 +0,0 @@
###
# Copyright (c) 2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import supybot.conf as conf
import supybot.registry as registry
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Alias')
def configure(advanced):
# This will be called by supybot to configure this module. advanced is
# a bool that specifies whether the user identified themself as an advanced
# user or not. You should effect your configuration by manipulating the
# registry as appropriate.
from supybot.questions import expect, anything, something, yn
conf.registerPlugin('Alias', True)
Alias = conf.registerPlugin('Alias')
conf.registerGroup(Alias, 'aliases')
conf.registerGroup(Alias, 'escapedaliases')
conf.registerGlobalValue(Alias, 'validName',
registry.String(r'^[^\x00-\x20]+$', _("""Regex which alias names must match in order to be valid""")))
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,175 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Supybot\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2012-04-27 15:36+0200\n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: German <fbesser@gmail.com>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Poedit-Language: German\n"
"X-Poedit-Country: GERMANY\n"
#: config.py:48
msgid "Regex which alias names must match in order to be valid"
msgstr ""
#: plugin.py:48
msgid ""
"Returns the channel the msg came over or the channel given in args.\n"
"\n"
" If the channel was given in args, args is modified (the channel is\n"
" removed).\n"
" "
msgstr ""
"Gibt den Kanal aus über den die Nachricht kam oder der Kanal der in den "
"Argumenten gegeben wurde.\n"
"\n"
"Falls der Kanal in den Argumenten angegeben wurde, werden die Argumente "
"bearbeitet (der Kanal wird entfernt."
#: plugin.py:110
msgid ""
"Encodes dots and pipes\n"
" Format: a<number of escaped chars>a(<index>(d|p))+<word without dots or "
"pipes>."
msgstr ""
#: plugin.py:226
msgid " at least"
msgstr "mindestens"
#: plugin.py:228 plugin.py:233
msgid ""
"<an alias,%s %n>\n"
"\n"
"Alias for %q."
msgstr ""
"<ein Alias, %s %n>\n"
"\n"
"Alias für %q."
#: plugin.py:229 plugin.py:234
msgid "argument"
msgstr "Argument"
#: plugin.py:239
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
" This plugin is only kept for backward compatibility, you should use the\n"
" built-in Aka plugin instead (you can migrate your existing aliases "
"using\n"
" the 'importaliasdatabase' command.\n"
"\n"
" To add an alias, `trout`, which expects a word as an argument::\n"
"\n"
" <jamessan> @alias add trout \"action slaps $1 with a large trout\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" To add an alias, `lastfm`, which expects a last.fm user and replies "
"with\n"
" their recently played items::\n"
"\n"
" @alias add lastfm \"rss [format concat http://ws.audioscrobbler."
"com/1.0/user/ [format concat [urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and `@lastfm` would "
"always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:357
msgid ""
"<alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
"<Alias>\n"
"\n"
"Versperrt ein Alias, sodass er nicht verändert werden kann."
#: plugin.py:365 plugin.py:378
msgid "There is no such alias."
msgstr "Es gibt keinen Alias mit diesem Namen."
#: plugin.py:370
msgid ""
"<alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
"<Alias>\n"
"\n"
"Entsperrt den Alias, sodass andere Personen ihn verändern können."
#: plugin.py:386
msgid "That name isn't valid. Try %q instead."
msgstr "Dieser Name ist nicht zulässig. Probiere anstatt %q."
#: plugin.py:426
#, fuzzy
msgid ""
"<name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand "
"argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, "
"etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, "
"@2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" remaining arguments,\" and cannot be combined with optional "
"arguments.\n"
" "
msgstr ""
"<Name> <Alias>\n"
"\n"
"Definiert einen Alias <Name> der <Alias> ausführt. <Alias> sollte in der "
"Standardform \"Befehl Argument [verschachtelter Befehl Argument\" angegeben "
"werden."
#: plugin.py:449
msgid ""
"<name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
"<Name>\n"
"\n"
"Entfernt den gegeben Alias, falls er nicht gesperrt ist."
#: plugin.py:463
msgid ""
"[--locked|--unlocked]\n"
"\n"
" Lists alias names of a particular type, defaults to all aliases if "
"no\n"
" --locked or --unlocked option is given.\n"
" "
msgstr ""
#: plugin.py:470
msgid "Cannot specify --locked and --unlocked simultaneously"
msgstr ""
#: plugin.py:486
msgid "There are no aliases of that type."
msgstr ""
#: plugin.py:488
#, fuzzy
msgid "There are no aliases."
msgstr "Es gibt keinen Alias mit diesem Namen."

View File

@ -1,204 +0,0 @@
# Alias plugin in Limnoria.
# Copyright (C) 2011, 2012 Limnoria
# Mikaela Suomalainen <mkaysi@outlook.com>, 2011, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: Supybot Alias plugin\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2014-12-20 13:47+0200\n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: suomi <>\n"
"Language: fi_FI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"X-Generator: Poedit 1.6.10\n"
#: config.py:48
msgid "Regex which alias names must match in order to be valid"
msgstr ""
#: plugin.py:48
msgid ""
"Returns the channel the msg came over or the channel given in args.\n"
"\n"
" If the channel was given in args, args is modified (the channel is\n"
" removed).\n"
" "
msgstr ""
"Palauttaa kanavan, jolta viesti tuli tai kanavan, joka on annettu "
"parametreissä.\n"
"\n"
" Jos kanava annetaan parametreissä, parametriä muokataan (kanava\n"
" poistetaan).\n"
" "
#: plugin.py:110
#, fuzzy
msgid ""
"Encodes dots and pipes\n"
" Format: a<number of escaped chars>a(<index>(d|p))+<word without dots or "
"pipes>."
msgstr ""
"Salaa [a-z0-9.]+ sisään [a-z][a-z0-9].\n"
" Muoto: a<ohitettujen merkkien määrä>a(<index>d)+<sana ilman pisteitä>."
#: plugin.py:226
msgid " at least"
msgstr "vähintään"
#: plugin.py:228 plugin.py:233
msgid ""
"<an alias,%s %n>\n"
"\n"
"Alias for %q."
msgstr ""
"<alias,%s %n>\n"
"\n"
"Alias %q:lle."
#: plugin.py:229 plugin.py:234
msgid "argument"
msgstr "parametri"
#: plugin.py:239
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
" This plugin is only kept for backward compatibility, you should use the\n"
" built-in Aka plugin instead (you can migrate your existing aliases "
"using\n"
" the 'importaliasdatabase' command.\n"
"\n"
" To add an alias, `trout`, which expects a word as an argument::\n"
"\n"
" <jamessan> @alias add trout \"action slaps $1 with a large trout\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" To add an alias, `lastfm`, which expects a last.fm user and replies "
"with\n"
" their recently played items::\n"
"\n"
" @alias add lastfm \"rss [format concat http://ws.audioscrobbler."
"com/1.0/user/ [format concat [urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and `@lastfm` would "
"always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:357
msgid ""
"<alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
"<alias>\n"
"\n"
" Lukitsee aliaksen, niin ettei kukaan muu voi muuttaa sitä.\n"
" "
#: plugin.py:365 plugin.py:378
msgid "There is no such alias."
msgstr "Tuollaista aliasta ei ole."
#: plugin.py:370
msgid ""
"<alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
"<alias>\n"
"\n"
" Poistaa lukituksen aliaksesta, jotta ihmiset vouvat määrittää uusia "
"aliaksia sen päälle.\n"
" "
#: plugin.py:386
msgid "That name isn't valid. Try %q instead."
msgstr "Tuo nimi ei ole kelvollinen. Yritä sen sijaan %q:ta."
#: plugin.py:426
msgid ""
"<name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand "
"argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, "
"etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, "
"@2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" remaining arguments,\" and cannot be combined with optional "
"arguments.\n"
" "
msgstr ""
"<nimi> <alias>\n"
"\n"
" Määrittää aliaksen <nimi>, joka suorittaa <komennon>. <Aliaksen>\n"
" pitäisi olla tavallinen \"komento parametri [sisäkkäinen komento "
"parametrit]\"\n"
" parametrejä aliakselle; ne täytetään ensimmäinen, toinen, jne.\n"
" Parametrit. $1, $2, jne. ovat vaadittava parametrejä. @1, @2,\n"
" jne. ovat valinnaisia parametrejä. $* tarkoittaa yksinkertaisesti "
"\"kaikki\n"
" jäljellä olevat parametrit,\" ja johon ei voida yhdistää vaihtoehtoisia "
"parametrejä.\n"
" "
#: plugin.py:449
msgid ""
"<name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
"<nimi>\n"
"\n"
" Poistaa annetun aliaksen jos se ei ole lukittu.\n"
" "
#: plugin.py:463
msgid ""
"[--locked|--unlocked]\n"
"\n"
" Lists alias names of a particular type, defaults to all aliases if "
"no\n"
" --locked or --unlocked option is given.\n"
" "
msgstr ""
#: plugin.py:470
msgid "Cannot specify --locked and --unlocked simultaneously"
msgstr ""
#: plugin.py:486
msgid "There are no aliases of that type."
msgstr ""
#: plugin.py:488
#, fuzzy
msgid "There are no aliases."
msgstr "Tuollaista aliasta ei ole."
#, fuzzy
#~ msgid ""
#~ "This plugin allows users to define aliases to commands and combinations\n"
#~ " of commands (via nesting)."
#~ msgstr ""
#~ "Tämä plugini sallii käyttäjien määrittää aliaksia komennoille ja "
#~ "komentojen yhdistelmille (sisäytyksellä)."
#~ msgid "You've attempted more nesting than is currently allowed on this bot."
#~ msgstr ""
#~ "Yritit sisällyttää useampia komentoja, kuin tämä botti sallii juuri nyt."

View File

@ -1,182 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: Limnoria <progval@gmail.com>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: ASCII\n"
"X-Generator: Poedit 1.5.4\n"
#: config.py:48
msgid "Regex which alias names must match in order to be valid"
msgstr ""
#: plugin.py:48
msgid ""
"Returns the channel the msg came over or the channel given in args.\n"
"\n"
" If the channel was given in args, args is modified (the channel is\n"
" removed).\n"
" "
msgstr ""
"Retourne le canal duquel vient le message ou le canal donné en argument.\n"
"\n"
"Si le canal était donné en argument, args est modifié (le canal est "
"supprimé)."
#: plugin.py:110
#, fuzzy
msgid ""
"Encodes dots and pipes\n"
" Format: a<number of escaped chars>a(<index>(d|p))+<word without dots or "
"pipes>."
msgstr "."
#: plugin.py:226
msgid " at least"
msgstr "au moins"
#: plugin.py:228 plugin.py:233
msgid ""
"<an alias,%s %n>\n"
"\n"
"Alias for %q."
msgstr ""
"<un alias,%s %n>\n"
"\n"
"Alias pour %q."
#: plugin.py:229 plugin.py:234
msgid "argument"
msgstr "argument"
#: plugin.py:239
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
" This plugin is only kept for backward compatibility, you should use the\n"
" built-in Aka plugin instead (you can migrate your existing aliases "
"using\n"
" the 'importaliasdatabase' command.\n"
"\n"
" To add an alias, `trout`, which expects a word as an argument::\n"
"\n"
" <jamessan> @alias add trout \"action slaps $1 with a large trout\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" To add an alias, `lastfm`, which expects a last.fm user and replies "
"with\n"
" their recently played items::\n"
"\n"
" @alias add lastfm \"rss [format concat http://ws.audioscrobbler."
"com/1.0/user/ [format concat [urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and `@lastfm` would "
"always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:357
msgid ""
"<alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
"<alias>\n"
"\n"
"Vérouille un alias pour que personne d'autre ne puisse le changer."
#: plugin.py:365 plugin.py:378
msgid "There is no such alias."
msgstr "Cet alias n'existe pas."
#: plugin.py:370
msgid ""
"<alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
"<alias>\n"
"\n"
"Déverrouille un alias de façon à ce que des gens puissent le redéfinir."
#: plugin.py:386
msgid "That name isn't valid. Try %q instead."
msgstr "Ce nom n'est pas valide. Essayez plutôt %q."
#: plugin.py:426
msgid ""
"<name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand "
"argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, "
"etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, "
"@2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" remaining arguments,\" and cannot be combined with optional "
"arguments.\n"
" "
msgstr ""
"<nom> <alias>\n"
"\n"
"Défini un alias <nom> qui exécute <alias>. L'<alias> peut être dans le "
"standard \"commande argument [commandeimbriquee argument]\". Les arguments "
"donnés à l'alias doivent être donnés dans l'ordre. Vous pouvez utiliser $1, "
"$2, etc pour symboliser les arguments obligatoires qui seront donnés à "
"l'alias, et @1, @2, etc pour symboliser ceux optionnels. $* signifie "
"simplement *tous* les arguments restants, et ne peut être combiné avec des "
"arguments optionnels."
#: plugin.py:449
msgid ""
"<name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
"<nom>\n"
"\n"
"Supprime l'alias donné, si il n'est pas verrouillé."
#: plugin.py:463
msgid ""
"[--locked|--unlocked]\n"
"\n"
" Lists alias names of a particular type, defaults to all aliases if "
"no\n"
" --locked or --unlocked option is given.\n"
" "
msgstr ""
#: plugin.py:470
msgid "Cannot specify --locked and --unlocked simultaneously"
msgstr ""
#: plugin.py:486
msgid "There are no aliases of that type."
msgstr ""
#: plugin.py:488
#, fuzzy
msgid "There are no aliases."
msgstr "Cet alias n'existe pas."
#~ msgid "You've attempted more nesting than is currently allowed on this bot."
#~ msgstr ""
#~ "Vous avez essayé dutiliser plus dimbrication que ce qui est "
#~ "actuellement autorisé sur ce bot."

View File

@ -1,182 +0,0 @@
# Limnoria Alias plugin.
# Copyright (C) 2011 Limnoria
# nyuszika7h <litemininyuszika@gmail.com>, 2011.
# Mikaela Suomalainen <mikaela.suomalainen@outlook.com>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: Limnoria Alias\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2012-04-27 15:12+0200\n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: \n"
"Language: hu_HU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
#: config.py:48
msgid "Regex which alias names must match in order to be valid"
msgstr ""
#: plugin.py:48
msgid ""
"Returns the channel the msg came over or the channel given in args.\n"
"\n"
" If the channel was given in args, args is modified (the channel is\n"
" removed).\n"
" "
msgstr ""
"Kiírja a csatorna nevét, ahonnan az üzenet jött, vagy a paraméterként "
"megadott csatornát.\n"
"\n"
"Ha a csatorna meg volt adva paraméterként, a paraméterek módosulnak (a "
"csatorna eltávolításra kerül)."
#: plugin.py:110
msgid ""
"Encodes dots and pipes\n"
" Format: a<number of escaped chars>a(<index>(d|p))+<word without dots or "
"pipes>."
msgstr ""
#: plugin.py:226
msgid " at least"
msgstr " legalább"
#: plugin.py:228 plugin.py:233
msgid ""
"<an alias,%s %n>\n"
"\n"
"Alias for %q."
msgstr ""
"<egy álnév,%s %n\n"
"\n"
"Álnév %q-ra."
#: plugin.py:229 plugin.py:234
msgid "argument"
msgstr "paraméter"
#: plugin.py:239
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
" This plugin is only kept for backward compatibility, you should use the\n"
" built-in Aka plugin instead (you can migrate your existing aliases "
"using\n"
" the 'importaliasdatabase' command.\n"
"\n"
" To add an alias, `trout`, which expects a word as an argument::\n"
"\n"
" <jamessan> @alias add trout \"action slaps $1 with a large trout\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" To add an alias, `lastfm`, which expects a last.fm user and replies "
"with\n"
" their recently played items::\n"
"\n"
" @alias add lastfm \"rss [format concat http://ws.audioscrobbler."
"com/1.0/user/ [format concat [urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and `@lastfm` would "
"always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:357
msgid ""
"<alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
"<álnév>\n"
"\n"
"Lezár egy álnevet, hogy senki más ne változtathassa meg."
#: plugin.py:365 plugin.py:378
msgid "There is no such alias."
msgstr "Nincs ilyen álnév."
#: plugin.py:370
msgid ""
"<alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
"<álnév>\n"
"\n"
"Feloldja egy álnév lezárását, hogy az emberek új álnevekkel írhassák felül."
#: plugin.py:386
msgid "That name isn't valid. Try %q instead."
msgstr "Az a név nem érvényes. Próbáld meg %q-t inkább."
#: plugin.py:426
msgid ""
"<name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand "
"argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, "
"etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, "
"@2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" remaining arguments,\" and cannot be combined with optional "
"arguments.\n"
" "
msgstr ""
"<név> <álnév>\n"
"\n"
"Meghatároz egy <név> nevű álnevet, amely futtatja <álnév> parancsot. Az "
"<álnév>-nek a szabványos \"parancs paraméter [beágyazottparancs paraméter]\" "
"álnév paraméterei formában kell lennie; ezek ki lesznek töltve az első, "
"második stb. paraméterekkel. $1, $2 stb. használható kötelező "
"paraméterekhez. @1, @2 stb. használható választható paraméterekhez. $* azt "
"jelenti, \"az összes hátralévő paraméter,\" és nem kombinálható választható "
"paraméterekkel."
#: plugin.py:449
msgid ""
"<name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
"<név>\n"
"\n"
"Eltávolítja a megadott álnevet, ha nincs lezárva."
#: plugin.py:463
msgid ""
"[--locked|--unlocked]\n"
"\n"
" Lists alias names of a particular type, defaults to all aliases if "
"no\n"
" --locked or --unlocked option is given.\n"
" "
msgstr ""
#: plugin.py:470
msgid "Cannot specify --locked and --unlocked simultaneously"
msgstr ""
#: plugin.py:486
msgid "There are no aliases of that type."
msgstr ""
#: plugin.py:488
#, fuzzy
msgid "There are no aliases."
msgstr "Nincs ilyen álnév."

View File

@ -1,183 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2011-06-07 08:23+0200\n"
"Last-Translator: skizzhg <skizzhg@gmx.com>\n"
"Language-Team: Italian <skizzhg@gmx.com>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: config.py:48
msgid "Regex which alias names must match in order to be valid"
msgstr ""
#: plugin.py:48
msgid ""
"Returns the channel the msg came over or the channel given in args.\n"
"\n"
" If the channel was given in args, args is modified (the channel is\n"
" removed).\n"
" "
msgstr ""
"Restituisce il canale da dove proviene il messaggio o il canale fornito come "
"argomento.\n"
"\n"
" Se il canale è stato dato come argomento, quest'ultimo viene modificato "
"(il canale\n"
" viene rimosso).\n"
" "
#: plugin.py:110
msgid ""
"Encodes dots and pipes\n"
" Format: a<number of escaped chars>a(<index>(d|p))+<word without dots or "
"pipes>."
msgstr ""
#: plugin.py:226
msgid " at least"
msgstr " almeno"
#: plugin.py:228 plugin.py:233
msgid ""
"<an alias,%s %n>\n"
"\n"
"Alias for %q."
msgstr ""
"<un alias,%s %n>\n"
"\n"
"Alias per %q."
#: plugin.py:229 plugin.py:234
msgid "argument"
msgstr "argomento"
#: plugin.py:239
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
" This plugin is only kept for backward compatibility, you should use the\n"
" built-in Aka plugin instead (you can migrate your existing aliases "
"using\n"
" the 'importaliasdatabase' command.\n"
"\n"
" To add an alias, `trout`, which expects a word as an argument::\n"
"\n"
" <jamessan> @alias add trout \"action slaps $1 with a large trout\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" To add an alias, `lastfm`, which expects a last.fm user and replies "
"with\n"
" their recently played items::\n"
"\n"
" @alias add lastfm \"rss [format concat http://ws.audioscrobbler."
"com/1.0/user/ [format concat [urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and `@lastfm` would "
"always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:357
msgid ""
"<alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
"<alias>\n"
"\n"
" Blocca un alias affinché nessun altro possa modificarlo.\n"
" "
#: plugin.py:365 plugin.py:378
msgid "There is no such alias."
msgstr "Non c'è nessun alias."
#: plugin.py:370
msgid ""
"<alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
"<alias>\n"
"\n"
" Sblocca un alias affinché chiunque possa ridefinirne di nuovi.\n"
" "
#: plugin.py:386
msgid "That name isn't valid. Try %q instead."
msgstr "Nome non valido. Prova %q invece."
#: plugin.py:426
msgid ""
"<name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand "
"argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, "
"etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, "
"@2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" remaining arguments,\" and cannot be combined with optional "
"arguments.\n"
" "
msgstr ""
"<nome> <comando>\n"
"\n"
" Definisce un <nome> che esegue <comando>. <comando> deve essere "
"nello\n"
" standard \"comando argomento [comando_nidificato argomento]\"; gli\n"
" argomenti dati devono essere riportati in sequenza. Per gli "
"argomenti\n"
" richiesti è possibile utilizzare $1, $2, ecc., mentre @1, @2, ecc. "
"per\n"
" quelli opzionali. $* significa semplicemente \"tutti gli argomenti\n"
" rimanenti\" e non può essere combinato con quelli opzionali.\n"
" "
#: plugin.py:449
msgid ""
"<name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
"<nome>\n"
"\n"
" Rimuove l'alias specificato, se questo non è bloccato.\n"
" "
#: plugin.py:463
msgid ""
"[--locked|--unlocked]\n"
"\n"
" Lists alias names of a particular type, defaults to all aliases if "
"no\n"
" --locked or --unlocked option is given.\n"
" "
msgstr ""
#: plugin.py:470
msgid "Cannot specify --locked and --unlocked simultaneously"
msgstr ""
#: plugin.py:486
msgid "There are no aliases of that type."
msgstr ""
#: plugin.py:488
#, fuzzy
msgid "There are no aliases."
msgstr "Non c'è nessun alias."

View File

@ -1,152 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: config.py:48
msgid "Regex which alias names must match in order to be valid"
msgstr ""
#: plugin.py:48
#, docstring
msgid ""
"Returns the channel the msg came over or the channel given in args.\n"
"\n"
" If the channel was given in args, args is modified (the channel is\n"
" removed).\n"
" "
msgstr ""
#: plugin.py:110
#, docstring
msgid ""
"Encodes dots and pipes\n"
" Format: a<number of escaped chars>a(<index>(d|p))+<word without dots or pipes>."
msgstr ""
#: plugin.py:226
msgid " at least"
msgstr ""
#: plugin.py:228 plugin.py:233
msgid ""
"<an alias,%s %n>\n"
"\n"
"Alias for %q."
msgstr ""
#: plugin.py:229 plugin.py:234
msgid "argument"
msgstr ""
#: plugin.py:239
#, docstring
msgid ""
"\n"
" This plugin allows users to define aliases to commands and combinations\n"
" of commands (via nesting).\n"
" This plugin is only kept for backward compatibility, you should use the\n"
" built-in Aka plugin instead (you can migrate your existing aliases using\n"
" the 'importaliasdatabase' command.\n"
"\n"
" To add an alias, `trout`, which expects a word as an argument::\n"
"\n"
" <jamessan> @alias add trout \"action slaps $1 with a large trout\"\n"
" <bot> jamessan: The operation succeeded.\n"
" <jamessan> @trout me\n"
" * bot slaps me with a large trout\n"
"\n"
" To add an alias, `lastfm`, which expects a last.fm user and replies with\n"
" their recently played items::\n"
"\n"
" @alias add lastfm \"rss [format concat http://ws.audioscrobbler.com/1.0/user/ [format concat [urlquote $1] /recenttracks.rss]]\"\n"
"\n"
" Note that if the nested commands being aliased hadn't been quoted, then\n"
" those commands would have been run immediately, and `@lastfm` would always\n"
" reply with the same information, the result of those commands.\n"
" "
msgstr ""
#: plugin.py:357
#, docstring
msgid ""
"<alias>\n"
"\n"
" Locks an alias so that no one else can change it.\n"
" "
msgstr ""
#: plugin.py:365 plugin.py:378
msgid "There is no such alias."
msgstr ""
#: plugin.py:370
#, docstring
msgid ""
"<alias>\n"
"\n"
" Unlocks an alias so that people can define new aliases over it.\n"
" "
msgstr ""
#: plugin.py:386
msgid "That name isn't valid. Try %q instead."
msgstr ""
#: plugin.py:426
#, docstring
msgid ""
"<name> <command>\n"
"\n"
" Defines an alias <name> that executes <command>. The <command>\n"
" should be in the standard \"command argument [nestedcommand argument]\"\n"
" arguments to the alias; they'll be filled with the first, second, etc.\n"
" arguments. $1, $2, etc. can be used for required arguments. @1, @2,\n"
" etc. can be used for optional arguments. $* simply means \"all\n"
" remaining arguments,\" and cannot be combined with optional arguments.\n"
" "
msgstr ""
#: plugin.py:449
#, docstring
msgid ""
"<name>\n"
"\n"
" Removes the given alias, if unlocked.\n"
" "
msgstr ""
#: plugin.py:463
#, docstring
msgid ""
"[--locked|--unlocked]\n"
"\n"
" Lists alias names of a particular type, defaults to all aliases if no\n"
" --locked or --unlocked option is given.\n"
" "
msgstr ""
#: plugin.py:470
msgid "Cannot specify --locked and --unlocked simultaneously"
msgstr ""
#: plugin.py:486
msgid "There are no aliases of that type."
msgstr ""
#: plugin.py:488
msgid "There are no aliases."
msgstr ""

View File

@ -1,496 +0,0 @@
###
# Copyright (c) 2002-2004, Jeremiah Fincher
# Copyright (c) 2014, James McCoy
# Copyright (c) 2012-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import re
import sys
import types
import supybot.conf as conf
import supybot.utils as utils
from supybot.commands import *
import supybot.utils.minisix as minisix
import supybot.ircutils as ircutils
import supybot.registry as registry
import supybot.callbacks as callbacks
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Alias')
# Copied from the old privmsgs.py.
def getChannel(irc, msg, args):
"""Returns the channel the msg came over or the channel given in args.
If the channel was given in args, args is modified (the channel is
removed).
"""
if args and msg.channel:
if conf.supybot.reply.requireChannelCommandsToBeSentInChannel():
if args[0] != msg.channel:
s = 'Channel commands must be sent in the channel to which ' \
'they apply; if this is not the behavior you desire, ' \
'ask the bot\'s administrator to change the registry ' \
'variable ' \
'supybot.reply.requireChannelCommandsToBeSentInChannel ' \
'to False.'
raise callbacks.Error(s)
return args.pop(0)
elif msg.channel:
return msg.channel
else:
raise callbacks.Error('Command must be sent in a channel or ' \
'include a channel in its arguments.')
def getArgs(args, required=1, optional=0, wildcard=0):
if len(args) < required:
raise callbacks.ArgumentError
if len(args) < required + optional:
ret = list(args) + ([''] * (required + optional - len(args)))
elif len(args) >= required + optional:
if not wildcard:
ret = list(args[:required + optional - 1])
ret.append(' '.join(args[required + optional - 1:]))
else:
ret = list(args)
return ret
class AliasError(Exception):
pass
dollarRe = re.compile(r'\$(\d+)')
def findBiggestDollar(alias):
dollars = dollarRe.findall(alias)
dollars = list(map(int, dollars))
dollars.sort()
if dollars:
return dollars[-1]
else:
return 0
atRe = re.compile(r'@(\d+)')
def findBiggestAt(alias):
ats = atRe.findall(alias)
ats = list(map(int, ats))
ats.sort()
if ats:
return ats[-1]
else:
return 0
def needsEscaping(alias):
return '.' in alias or '|' in alias
def escapeAlias(alias):
"""Encodes dots and pipes
Format: a<number of escaped chars>a(<index>(d|p))+<word without dots or pipes>."""
prefix = ''
new_alias = ''
prefixes = 0
for index, char in enumerate(alias):
if char == '.':
prefix += '%sd' % index
prefixes += 1
elif char == '|':
prefix += '%sp' % index
prefixes += 1
else:
new_alias += char
pre_prefix = 'a%ia' % prefixes
return pre_prefix + prefix + new_alias
def unescapeAlias(alias):
alias = alias[1:] # Strip the leading 'a'
escaped_nb = ''
while alias[0] in '0123456789':
escaped_nb += alias[0]
alias = alias[1:]
alias = alias[1:]
escaped_nb = int(escaped_nb)
escaped_chars = []
while alias[0] in '0123456789':
current_group = ''
while alias[0] in '0123456789':
current_group += alias[0]
alias = alias[1:]
if alias[0] == 'd':
char = '.'
elif alias[0] == 'p':
char = '|'
else:
char = alias[0]
alias = alias[1:]
escaped_chars.append((int(current_group), char))
if len(escaped_chars) == escaped_nb:
break
new_alias = ''
index = 0
for char in alias:
if escaped_chars and index == escaped_chars[0][0]:
new_alias += escaped_chars[0][1]
escaped_chars.pop(0)
index += 1
new_alias += char
index += 1
return new_alias
def makeNewAlias(name, alias):
original = alias
biggestDollar = findBiggestDollar(original)
biggestAt = findBiggestAt(original)
wildcard = '$*' in original
if biggestAt and wildcard:
raise AliasError('Can\'t mix $* and optional args (@1, etc.)')
if original.count('$*') > 1:
raise AliasError('There can be only one $* in an alias.')
testTokens = callbacks.tokenize(original)
if testTokens and isinstance(testTokens[0], list):
raise AliasError('Commands may not be the result of nesting.')
def f(self, irc, msg, args):
alias = original.replace('$nick', msg.nick)
if '$channel' in original:
channel = getChannel(irc, msg, args)
alias = alias.replace('$channel', channel)
tokens = callbacks.tokenize(alias)
if biggestDollar or biggestAt:
args = getArgs(args, required=biggestDollar, optional=biggestAt,
wildcard=wildcard)
max_len = conf.supybot.reply.maximumLength()
args = list([x[:max_len] for x in args])
def regexpReplace(m):
idx = int(m.group(1))
return args[idx-1]
def replace(tokens, replacer):
for (i, token) in enumerate(tokens):
if isinstance(token, list):
replace(token, replacer)
else:
tokens[i] = replacer(token)
replace(tokens, lambda s: dollarRe.sub(regexpReplace, s))
if biggestAt:
assert not wildcard
args = args[biggestDollar:]
replace(tokens, lambda s: atRe.sub(regexpReplace, s))
if wildcard:
assert not biggestAt
# Gotta remove the things that have already been subbed in.
i = biggestDollar
while i:
args.pop(0)
i -= 1
def everythingReplace(tokens):
for (i, token) in enumerate(tokens):
if isinstance(token, list):
if everythingReplace(token):
return
if token == '$*':
tokens[i:i+1] = args
return True
elif '$*' in token:
tokens[i] = token.replace('$*', ' '.join(args))
return True
return False
everythingReplace(tokens)
# Limit memory use by constraining the size of the message being passed
# in to the alias. Also tracking nesting to avoid endless recursion.
maxLength = conf.supybot.reply.maximumLength()
tokens = [t[:maxLength] for t in tokens]
self.Proxy(irc, msg, tokens, nested=irc.nested + 1)
flexargs = ''
if biggestDollar and (wildcard or biggestAt):
flexargs = _(' at least')
try:
doc = format(_('<an alias,%s %n>\n\nAlias for %q.'),
flexargs, (biggestDollar, _('argument')), alias)
except UnicodeDecodeError:
if minisix.PY2:
alias = alias.decode('utf8')
doc = format(_('<an alias,%s %n>\n\nAlias for %q.'),
flexargs, (biggestDollar, _('argument')), alias)
f = utils.python.changeFunctionName(f, name, doc)
return f
class Alias(callbacks.Plugin):
"""
This plugin allows users to define aliases to commands and combinations
of commands (via nesting).
This plugin is only kept for backward compatibility, you should use the
built-in Aka plugin instead (you can migrate your existing aliases using
the 'importaliasdatabase' command.
To add an alias, ``trout``, which expects a word as an argument::
<jamessan> @alias add trout "action slaps $1 with a large trout"
<bot> jamessan: The operation succeeded.
<jamessan> @trout me
* bot slaps me with a large trout
Add an alias, ``randpercent``, which returns a random percentage value::
@alias add randpercent "squish [dice 1d100]%"
This requires the ``Filter`` and ``Games`` plugins to be loaded.
Note that nested commands in an alias should be quoted, or they will only
run once when you create the alias, and not each time the alias is
called. (In this case, not quoting the nested command would mean that
``@randpercent`` always responds with the same value!)
"""
def __init__(self, irc):
self.__parent = super(Alias, self)
self.__parent.__init__(irc)
# Schema: {alias: [command, locked, commandMethod]}
self.aliases = {}
# XXX This should go. aliases should be a space separate list, etc.
group = conf.supybot.plugins.Alias.aliases
group2 = conf.supybot.plugins.Alias.escapedaliases
prefixLen = len(registry.split('supybot.plugins.alias.aliases'))
for (name, alias) in registry._cache.items():
name = name.lower()
nameSplit = registry.split(name)
if len(nameSplit) > prefixLen+1:
continue
if name.startswith('supybot.plugins.alias.aliases.'):
name = nameSplit[-1]
conf.registerGlobalValue(group, name, registry.String('', ''))
conf.registerGlobalValue(group.get(name), 'locked',
registry.Boolean(False, ''))
elif name.startswith('supybot.plugins.alias.escapedaliases.'):
name = nameSplit[-1]
conf.registerGlobalValue(group2, name,
registry.String('', ''))
conf.registerGlobalValue(group2.get(name),
'locked', registry.Boolean(False, ''))
for (name, value) in group.getValues(fullNames=False):
name = name.lower() # Just in case.
command = value()
locked = value.locked()
self.aliases[name] = [command, locked, None]
for (name, value) in group2.getValues(fullNames=False):
name = name.lower() # Just in case.
command = value()
locked = value.locked()
self.aliases[unescapeAlias(name)] = [command, locked, None]
for (alias, (command, locked, _)) in self.aliases.copy().items():
try:
self.addAlias(irc, alias, command, locked)
except Exception as e:
self.log.exception('Exception when trying to add alias %s. '
'Removing from the Alias database.', alias)
del self.aliases[alias]
def isCommandMethod(self, name):
if not self.__parent.isCommandMethod(name):
if name in self.aliases:
return True
else:
return False
else:
return True
def listCommands(self):
return self.__parent.listCommands(self.aliases.keys())
def getCommandMethod(self, command):
try:
return self.__parent.getCommandMethod(command)
except AttributeError:
return self.aliases[command[0]][2]
def aliasRegistryGroup(self, name):
if needsEscaping(name):
return self.registryValue('escapedaliases', value=False)
else:
return self.registryValue('aliases', value=False)
def aliasRegistryNode(self, name):
group = self.aliasRegistryGroup(name)
if needsEscaping(name):
return group.get(escapeAlias(name))
else:
return group.get(name)
def aliasRegistryRemove(self, name):
group = self.aliasRegistryGroup(name)
if needsEscaping(name):
group.unregister(escapeAlias(name))
else:
group.unregister(name)
def setLocked(self, name, value):
self.aliases[name][1] = value
self.aliasRegistryNode(name).locked.setValue(value)
def isValidName(self, name):
if not re.search(self.registryValue('validName'), name):
return False
if not registry.isValidRegistryName(name):
return False
return True
@internationalizeDocstring
def lock(self, irc, msg, args, name):
"""<alias>
Locks an alias so that no one else can change it.
"""
if name in self.aliases and self.isCommandMethod(name):
self.setLocked(name, True)
irc.replySuccess()
else:
irc.error(_('There is no such alias.'))
lock = wrap(lock, [('checkCapability', 'admin'), 'commandName'])
@internationalizeDocstring
def unlock(self, irc, msg, args, name):
"""<alias>
Unlocks an alias so that people can define new aliases over it.
"""
if name in self.aliases and self.isCommandMethod(name):
self.setLocked(name, False)
irc.replySuccess()
else:
irc.error(_('There is no such alias.'))
unlock = wrap(unlock, [('checkCapability', 'admin'), 'commandName'])
def addAlias(self, irc, name, alias, lock=False):
if not self.isValidName(name):
raise AliasError('Invalid alias name.')
realName = callbacks.canonicalName(name)
if name != realName:
s = format(_('That name isn\'t valid. Try %q instead.'), realName)
raise AliasError(s)
name = realName
if self.isCommandMethod(name):
if realName not in self.aliases:
s = 'You can\'t overwrite commands in this plugin.'
raise AliasError(s)
if name in self.aliases:
(currentAlias, locked, _) = self.aliases[name]
if locked and currentAlias != alias:
raise AliasError(format('Alias %q is locked.', name))
f = makeNewAlias(name, alias)
f = types.MethodType(f, self)
if name in self.aliases:
# We gotta remove it so its value gets updated.
self.aliasRegistryRemove(name)
aliasGroup = self.aliasRegistryGroup(name)
if needsEscaping(name):
confname = escapeAlias(name)
else:
confname = name
conf.registerGlobalValue(aliasGroup, confname,
registry.String(alias, ''))
conf.registerGlobalValue(aliasGroup.get(confname), 'locked',
registry.Boolean(lock, ''))
self.aliases[name] = [alias, lock, f]
def removeAlias(self, name, evenIfLocked=False):
name = callbacks.canonicalName(name)
if name in self.aliases and self.isCommandMethod(name):
if evenIfLocked or not self.aliases[name][1]:
del self.aliases[name]
self.aliasRegistryRemove(name)
else:
raise AliasError('That alias is locked.')
else:
raise AliasError('There is no such alias.')
@internationalizeDocstring
def add(self, irc, msg, args, name, alias):
"""<name> <command>
Defines an alias <name> that executes <command>. The <command>
should be in the standard "command argument [nestedcommand argument]"
arguments to the alias; they'll be filled with the first, second, etc.
arguments. $1, $2, etc. can be used for required arguments. @1, @2,
etc. can be used for optional arguments. $* simply means "all
remaining arguments," and cannot be combined with optional arguments.
"""
if ' ' not in alias:
# If it's a single word, they probably want $*.
alias += ' $*'
try:
self.addAlias(irc, name, alias)
self.log.info('Adding alias %q for %q (from %s)',
name, alias, msg.prefix)
irc.replySuccess()
except AliasError as e:
irc.error(str(e))
add = wrap(add, ['commandName', 'text'])
@internationalizeDocstring
def remove(self, irc, msg, args, name):
"""<name>
Removes the given alias, if unlocked.
"""
try:
self.removeAlias(name)
self.log.info('Removing alias %q (from %s)', name, msg.prefix)
irc.replySuccess()
except AliasError as e:
irc.error(str(e))
remove = wrap(remove, ['commandName'])
@internationalizeDocstring
def list(self, irc, msg, args, optlist):
"""[--locked|--unlocked]
Lists alias names of a particular type, defaults to all aliases if no
--locked or --unlocked option is given.
"""
optlist = dict(optlist)
if len(optlist)>1:
irc.error(_('Cannot specify --locked and --unlocked simultaneously'))
return
aliases = []
for name in self.aliases.keys():
if self.isCommandMethod(name):
if 'locked' in optlist:
if self.aliases[name][1]: aliases.append(name)
elif 'unlocked' in optlist:
if not self.aliases[name][1]: aliases.append(name)
else:
aliases.append(name)
if aliases:
aliases.sort()
irc.reply(format('%L', aliases))
else:
if len(optlist):
irc.reply(_('There are no aliases of that type.'))
else:
irc.reply(_('There are no aliases.'))
list = wrap(list, [getopts({'locked':'', 'unlocked':''})])
Class = Alias
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,185 +0,0 @@
# -*- coding: utf8 -*-
###
# Copyright (c) 2002-2004, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
from supybot.test import *
import supybot.conf as conf
import supybot.plugin as plugin
import supybot.registry as registry
from supybot.utils.minisix import u
from . import plugin as Alias
class FunctionsTest(SupyTestCase):
def testFindBiggestDollar(self):
self.assertEqual(Alias.findBiggestDollar(''), 0)
self.assertEqual(Alias.findBiggestDollar('foo'), 0)
self.assertEqual(Alias.findBiggestDollar('$0'), 0)
self.assertEqual(Alias.findBiggestDollar('$1'), 1)
self.assertEqual(Alias.findBiggestDollar('$2'), 2)
self.assertEqual(Alias.findBiggestDollar('$2 $10'), 10)
self.assertEqual(Alias.findBiggestDollar('$3'), 3)
self.assertEqual(Alias.findBiggestDollar('$3 $2 $1'), 3)
self.assertEqual(Alias.findBiggestDollar('foo bar $1'), 1)
self.assertEqual(Alias.findBiggestDollar('foo $2 $1'), 2)
self.assertEqual(Alias.findBiggestDollar('foo $0 $1'), 1)
self.assertEqual(Alias.findBiggestDollar('foo $1 $3'), 3)
self.assertEqual(Alias.findBiggestDollar('$10 bar $1'), 10)
class AliasTestCase(ChannelPluginTestCase):
plugins = ('Alias', 'Filter', 'Utilities', 'Format', 'Reply')
def testNoAliasWithNestedCommandName(self):
self.assertError('alias add foo "[bar] baz"')
def testDoesNotOverwriteCommands(self):
# We don't have dispatcher commands anymore
#self.assertError('alias add alias "echo foo bar baz"')
self.assertError('alias add add "echo foo bar baz"')
self.assertError('alias add remove "echo foo bar baz"')
self.assertError('alias add lock "echo foo bar baz"')
self.assertError('alias add unlock "echo foo bar baz"')
def testAliasHelp(self):
self.assertNotError('alias add slashdot foo')
self.assertRegexp('help slashdot', "Alias for .*foo")
self.assertNotError('alias add nonascii echo éé')
self.assertRegexp('help nonascii', "Alias for .*echo éé")
def testRemove(self):
self.assertNotError('alias add foo echo bar')
self.assertResponse('foo', 'bar')
self.assertNotError('alias remove foo')
self.assertError('foo')
def testDollars(self):
self.assertNotError('alias add rot26 "rot13 [rot13 $1]"')
self.assertResponse('rot26 foobar', 'foobar')
def testMoreDollars(self):
self.assertNotError('alias add rev "echo $3 $2 $1"')
self.assertResponse('rev foo bar baz', 'baz bar foo')
def testAllArgs(self):
self.assertNotError('alias add swap "echo $2 $1 $*"')
self.assertResponse('swap 1 2 3 4 5', '2 1 3 4 5')
self.assertError('alias add foo "echo $1 @1 $*"')
self.assertNotError('alias add moo echo $1 $*')
self.assertError('moo')
self.assertResponse('moo foo', 'foo')
self.assertResponse('moo foo bar', 'foo bar')
def testChannel(self):
self.assertNotError('alias add channel echo $channel')
self.assertResponse('alias channel', self.channel)
def testNick(self):
self.assertNotError('alias add sendingnick "rot13 [rot13 $nick]"')
self.assertResponse('sendingnick', self.nick)
def testAddRemoveAlias(self):
cb = self.irc.getCallback('Alias')
cb.addAlias(self.irc, 'foobar', 'echo sbbone', lock=True)
self.assertResponse('foobar', 'sbbone')
self.assertRaises(Alias.AliasError, cb.removeAlias, 'foobar')
cb.removeAlias('foobar', evenIfLocked=True)
self.assertFalse('foobar' in cb.aliases)
self.assertError('foobar')
self.assertRegexp('alias add abc\x07 ignore', 'Error.*Invalid')
def testOptionalArgs(self):
self.assertNotError('alias add myrepr "repr @1"')
self.assertResponse('myrepr foo', '"foo"')
self.assertResponse('myrepr ""', '""')
def testNoExtraSpaces(self):
self.assertNotError('alias add foo "action takes $1\'s money"')
self.assertResponse('foo bar', '\x01ACTION takes bar\'s money\x01')
def testNoExtraQuotes(self):
self.assertNotError('alias add myre "echo s/$1/$2/g"')
self.assertResponse('myre foo bar', 's/foo/bar/g')
def testUnicode(self):
self.assertNotError(u('alias add \u200b echo foo'))
self.assertResponse(u('\u200b'), 'foo')
self.assertNotError('alias add café echo bar')
self.assertResponse('café', 'bar')
def testSimpleAliasWithoutArgsImpliesDollarStar(self):
self.assertNotError('alias add exo echo')
self.assertResponse('exo foo bar baz', 'foo bar baz')
class EscapedAliasTestCase(ChannelPluginTestCase):
plugins = ('Alias', 'Utilities')
def setUp(self):
registry._cache.update(
{'supybot.plugins.Alias.escapedaliases.a1a3dfoobar': 'echo baz',
'supybot.plugins.Alias.escapedaliases.a1a3dfoobar.locked': 'False'})
super(EscapedAliasTestCase, self).setUp()
def testReadDatabase(self):
self.assertResponse('foo.bar', 'baz')
def testAdd(self):
self.assertNotError('alias add spam.egg echo hi')
self.assertResponse('spam.egg', 'hi')
self.assertNotError('alias add spam|egg echo hey')
self.assertResponse('spam|egg', 'hey')
self.assertNotError('alias remove spam.egg')
self.assertError('spam.egg')
self.assertNotError('spam|egg')
self.assertNotError('alias remove spam|egg')
self.assertError('spam.egg')
self.assertError('spam|egg')
def testWriteDatabase(self):
self.assertNotError('alias add fooo.spam echo egg')
self.assertResponse('fooo.spam', 'egg')
self.assertTrue(hasattr(conf.supybot.plugins.Alias.escapedaliases,
'a1a4dfooospam'))
self.assertEqual(conf.supybot.plugins.Alias.escapedaliases.a1a4dfooospam(),
'echo egg')
self.assertNotError('alias add foo.spam.egg echo supybot')
self.assertResponse('foo.spam.egg', 'supybot')
self.assertTrue(hasattr(conf.supybot.plugins.Alias.escapedaliases,
'a2a3d8dfoospamegg'))
self.assertEqual(conf.supybot.plugins.Alias.escapedaliases.a2a3d8dfoospamegg(),
'echo supybot')
self.assertEqual(Alias.unescapeAlias('a2a3d8dfoospamegg'),
'foo.spam.egg')
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,118 +0,0 @@
.. _plugin-Anonymous:
Documentation for the Anonymous plugin for Supybot
==================================================
Purpose
-------
Allows folks to talk through the bot anonymously.
Usage
-----
This plugin allows users to act through the bot anonymously. The 'do'
command has the bot perform an anonymous action in a given channel, and
the 'say' command allows other people to speak through the bot. Since
this can be fairly well abused, you might want to set
supybot.plugins.Anonymous.requireCapability so only users with that
capability can use this plugin. For extra security, you can require that
the user be *in* the channel they are trying to address anonymously with
supybot.plugins.Anonymous.requirePresenceInChannel, or you can require
that the user be registered by setting
supybot.plugins.Anonymous.requireRegistration.
Example: Proving that you are the owner
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When you ask for cloak/vhost for your bot, the network operators will
often ask you to prove that you own the bot. You can do this for example
with the following method::
@load Anonymous
@config plugins.anonymous.requirecapability owner
@config plugins.anonymous.allowprivatetarget True
@anonymous say <operator nick> Hi, my owner is <your nick> :)
This
* Loads the plugin.
* Makes the plugin require that you are the owner
* If anyone could send private messages as the bot, they could also
access network services.
* Allows sending private messages
* Sends message ``Hi, my owner is <your nick> :)`` to ``operator nick``.
* Note that you won't see the messages that are sent to the bot.
.. _commands-Anonymous:
Commands
--------
.. _command-anonymous-do:
do <channel> <action>
Performs <action> in <channel>.
.. _command-anonymous-react:
react <channel> <reaction> <nick>
Sends the <reaction> to <nick>'s last message. <reaction> is typically a smiley or an emoji. This may not be supported on the current network, as this command depends on IRCv3 features. This is also not supported if supybot.protocols.irc.experimentalExtensions disabled (don't enable it unless you know what you are doing).
.. _command-anonymous-say:
say <channel> <text>
Sends <text> to <channel>.
.. _command-anonymous-tell:
tell <nick> <text>
Sends <text> to <nick>. Can only be used if supybot.plugins.Anonymous.allowPrivateTarget is True.
.. _conf-Anonymous:
Configuration
-------------
.. _conf-supybot.plugins.Anonymous.allowPrivateTarget:
supybot.plugins.Anonymous.allowPrivateTarget
This config variable defaults to "False", is not network-specific, and is not channel-specific.
Determines whether the bot will allow the "tell" command to be used. If true, the bot will allow the "tell" command to send private messages to other users.
.. _conf-supybot.plugins.Anonymous.public:
supybot.plugins.Anonymous.public
This config variable defaults to "True", is not network-specific, and is not channel-specific.
Determines whether this plugin is publicly visible.
.. _conf-supybot.plugins.Anonymous.requireCapability:
supybot.plugins.Anonymous.requireCapability
This config variable defaults to "", is network-specific, and is channel-specific.
Determines what capability (if any) the bot should require people trying to use this plugin to have.
.. _conf-supybot.plugins.Anonymous.requirePresenceInChannel:
supybot.plugins.Anonymous.requirePresenceInChannel
This config variable defaults to "True", is network-specific, and is channel-specific.
Determines whether the bot should require people trying to use this plugin to be in the channel they wish to anonymously send to.
.. _conf-supybot.plugins.Anonymous.requireRegistration:
supybot.plugins.Anonymous.requireRegistration
This config variable defaults to "True", is network-specific, and is channel-specific.
Determines whether the bot should require people trying to use this plugin to be registered.

View File

@ -1,63 +0,0 @@
###
# Copyright (c) 2005, Daniel DiPaolo
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
"""
Allows folks to talk through the bot anonymously.
"""
import supybot
import supybot.world as world
# Use this for the version of this plugin. You may wish to put a CVS keyword
# in here if you're keeping the plugin in CVS or some similar system.
__version__ = "%%VERSION%%"
__author__ = supybot.authors.strike
__maintainer__ = supybot.authors.limnoria_core
# This is a dictionary mapping supybot.Author instances to lists of
# contributions.
__contributors__ = {}
from . import config
from . import plugin
from importlib import reload
reload(plugin) # In case we're being reloaded.
# Add more reloads here if you add third-party modules and want them to be
# reloaded when this plugin is reloaded. Don't forget to import them as well!
if world.testing:
from . import test
Class = plugin.Class
configure = config.configure
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,65 +0,0 @@
###
# Copyright (c) 2005, Daniel DiPaolo
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import supybot.conf as conf
import supybot.registry as registry
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Anonymous')
def configure(advanced):
# This will be called by supybot to configure this module. advanced is
# a bool that specifies whether the user identified themself as an advanced
# user or not. You should effect your configuration by manipulating the
# registry as appropriate.
from supybot.questions import expect, anything, something, yn
conf.registerPlugin('Anonymous', True)
Anonymous = conf.registerPlugin('Anonymous')
# This is where your configuration variables (if any) should go. For example:
# conf.registerGlobalValue(Anonymous, 'someConfigVariableName',
# registry.Boolean(False, """Help for someConfigVariableName."""))
conf.registerChannelValue(conf.supybot.plugins.Anonymous,
'requirePresenceInChannel', registry.Boolean(True, _("""Determines whether
the bot should require people trying to use this plugin to be in the
channel they wish to anonymously send to.""")))
conf.registerChannelValue(conf.supybot.plugins.Anonymous, 'requireRegistration',
registry.Boolean(True, _("""Determines whether the bot should require
people trying to use this plugin to be registered.""")))
conf.registerChannelValue(conf.supybot.plugins.Anonymous, 'requireCapability',
registry.String('', _("""Determines what capability (if any) the bot should
require people trying to use this plugin to have.""")))
conf.registerGlobalValue(conf.supybot.plugins.Anonymous, 'allowPrivateTarget',
registry.Boolean(False, _("""Determines whether the bot will allow the
"tell" command to be used. If true, the bot will allow the "tell"
command to send private messages to other users.""")))
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,202 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Supybot\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2011-10-28 12:55+0100\n"
"Last-Translator: Florian Besser <fbesser@gmail.com>\n"
"Language-Team: German <fbesser@gmail.com>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Poedit-Language: de\n"
#: config.py:50
msgid ""
"Determines whether\n"
" the bot should require people trying to use this plugin to be in the\n"
" channel they wish to anonymously send to."
msgstr "Legt fest ob Leute im Kanal sein müssen, an den anonym senden wollen."
#: config.py:54
msgid ""
"Determines whether the bot should require\n"
" people trying to use this plugin to be registered."
msgstr ""
"Legt fest ob Nutzer registiert sein müssen um dieses Plugin zu benutze."
#: config.py:57
msgid ""
"Determines what capability (if any) the bot should\n"
" require people trying to use this plugin to have."
msgstr ""
"Legt fest welche Fähgikeiten (falls überhaupt) der Bot verlangt von Personen "
"die versuchen dieses Plugin zu benutzen."
#: config.py:60
#, fuzzy
msgid ""
"Determines whether the bot will allow the\n"
" \"tell\" command to be used. If true, the bot will allow the \"tell\"\n"
" command to send private messages to other users."
msgstr ""
"Legt fest ob der Bot verlangt, dass Ziele des Befehls \"say\" öffentlich "
"sind (z.B. Kanäle). Falls das auf True gesetzt ist, wird ber Bot Nutzern "
"erlauben den Befehl \"say\" zu nutzen um anderen Nutzern private Nachrichten "
"zu senden."
#: plugin.py:45
#, fuzzy
msgid ""
"\n"
" This plugin allows users to act through the bot anonymously. The 'do'\n"
" command has the bot perform an anonymous action in a given channel, and\n"
" the 'say' command allows other people to speak through the bot. Since\n"
" this can be fairly well abused, you might want to set\n"
" supybot.plugins.Anonymous.requireCapability so only users with that\n"
" capability can use this plugin. For extra security, you can require "
"that\n"
" the user be *in* the channel they are trying to address anonymously "
"with\n"
" supybot.plugins.Anonymous.requirePresenceInChannel, or you can require\n"
" that the user be registered by setting\n"
" supybot.plugins.Anonymous.requireRegistration.\n"
"\n"
" Example: Proving that you are the owner\n"
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" When you ask for cloak/vhost for your bot, the network operators will\n"
" often ask you to prove that you own the bot. You can do this for "
"example\n"
" with the following method::\n"
"\n"
" @load Anonymous\n"
" @config plugins.anonymous.requirecapability owner\n"
" @config plugins.anonymous.allowprivatetarget True\n"
" @anonymous say <operator nick> Hi, my owner is <your nick> :)\n"
"\n"
" This\n"
" * Loads the plugin.\n"
" * Makes the plugin require that you are the owner\n"
"\n"
" * If anyone could send private messages as the bot, they could also\n"
" access network services.\n"
"\n"
" * Allows sending private messages\n"
" * Sends message ``Hi, my owner is <your nick> :)`` to ``operator "
"nick``.\n"
"\n"
" * Note that you won't see the messages that are sent to the bot.\n"
"\n"
" "
msgstr ""
"Das Plugin erlaubt Nutzern durch den Bot anonym zu bleiben. Der 'do' Befehl "
"lässt den Bot eine anonyme Aktion in einem Kanal ausführen und der 'say' "
"Befehl lässt Nutzer durch den Bot sprechen. Da das Ganze natürlich leicht "
"missbraucht werden kann, willst du vielleicht supybot.plugins.Anonymous."
"requireCapability setzen, sodass nur Nutzer mit dieser Fähigkeit das Plugin "
"benutzen können. Für etwas mehr Sicherheit kannst du mit supybot.plugins."
"Anonymous.requirePresenceInChannel verlangen, dass der Nutzer in dem Kanal "
"sein muss in dem er anonym senden will oder du kannst verlangen, dass der "
"Nutzer registriert sein muss indem du supybot.plugins.Anonymous."
"requireRegistration setzt."
#: plugin.py:98
msgid "You must be in %s to %q in there."
msgstr "Du musst in %s sein um %q dort auszuführen."
#: plugin.py:102
msgid "I'm lobotomized in %s."
msgstr "Ich bin hirnamputiert in %s."
#: plugin.py:105
msgid ""
"That channel has set its capabilities so as to disallow the use of this "
"plugin."
msgstr ""
"Für den Kanal sind die Fähigkeiten so gesetzt, dass sie das benutzen dieses "
"Plugins nicht erlauben."
#: plugin.py:108
msgid ""
"This command is disabled (supybot.plugins.Anonymous.allowPrivateTarget is "
"False)."
msgstr ""
#: plugin.py:112
#, fuzzy
msgid ""
"<channel> <text>\n"
"\n"
" Sends <text> to <channel>.\n"
" "
msgstr ""
"<Kanal> <Aktion>\n"
"\n"
"Führt die <Aktion> im <Kanal> aus."
#: plugin.py:124
#, fuzzy
msgid ""
"<nick> <text>\n"
"\n"
" Sends <text> to <nick>. Can only be used if\n"
" supybot.plugins.Anonymous.allowPrivateTarget is True.\n"
" "
msgstr ""
"<Kanal|Nick> <text>\n"
"\n"
"Sendet <Text> an <Kanal|Nick>. Kann nur an <Nick> senden wenn supybot."
"plugins.Anonymous.allowPrivateTarget auf True gesetzt ist."
#: plugin.py:137
msgid ""
"<channel> <action>\n"
"\n"
" Performs <action> in <channel>.\n"
" "
msgstr ""
"<Kanal> <Aktion>\n"
"\n"
"Führt die <Aktion> im <Kanal> aus."
#: plugin.py:148
msgid ""
"<channel> <reaction> <nick>\n"
"\n"
" Sends the <reaction> to <nick>'s last message.\n"
" <reaction> is typically a smiley or an emoji.\n"
"\n"
" This may not be supported on the current network, as this\n"
" command depends on IRCv3 features.\n"
" This is also not supported if\n"
" supybot.protocols.irc.experimentalExtensions disabled\n"
" (don't enable it unless you know what you are doing).\n"
" "
msgstr ""
#: plugin.py:162
msgid ""
"Unable to react, supybot.protocols.irc.experimentalExtensions is disabled."
msgstr ""
#: plugin.py:167
msgid "Unable to react, the network does not support message-tags."
msgstr ""
#: plugin.py:172
msgid ""
"Unable to react, the network does not allow draft/reply and/or draft/react."
msgstr ""
#: plugin.py:181
msgid "I couldn't find a message from %s in my history of %s messages."
msgstr ""
#: plugin.py:189
msgid "Unable to react, %s's last message does not have a message id."
msgstr ""
#~ msgid "%q cannot be used to send private messages."
#~ msgstr "%q kann nicht verwendet werden um private Nachrichten zu versenden."

View File

@ -1,226 +0,0 @@
# Anonymous plugin in Limnoria.
# Copyright (C) 2011-2014 Limnoria
# Mikaela Suomalainen <mikaela.suomalainen@outlook.com>, 2011-2014.
#
msgid ""
msgstr ""
"Project-Id-Version: Supybot Anonymous\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: \n"
"Language: fi_FI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.10\n"
#: config.py:50
msgid ""
"Determines whether\n"
" the bot should require people trying to use this plugin to be in the\n"
" channel they wish to anonymously send to."
msgstr ""
"Määrittää vaatiiko \n"
"botti ihmisten, jotka yrittävät käyttää tätä lisäosaa, olemaan\n"
"kanavalla, jonne he tahtovat lähettää viestin tuntemattomasti."
#: config.py:54
msgid ""
"Determines whether the bot should require\n"
" people trying to use this plugin to be registered."
msgstr ""
"Määrittää vaatiiko botti\n"
"ihmisiä, jotka yrittävät käyttää tätä lisäosaa, olemaan rekisteröityneitä."
#: config.py:57
msgid ""
"Determines what capability (if any) the bot should\n"
" require people trying to use this plugin to have."
msgstr ""
"Määrittää minkä valtuuden (jos minkään) botti vaatii\n"
" ihmisiltä, jotka yrittävät käyttää tätä lisäosaa."
#: config.py:60
#, fuzzy
msgid ""
"Determines whether the bot will allow the\n"
" \"tell\" command to be used. If true, the bot will allow the \"tell\"\n"
" command to send private messages to other users."
msgstr ""
"Määrittää salliiko botti \"tell\"-komennon käytön. Jos tämä on True, botti "
"sallii \"tell\"-komennon\n"
" lähettävän yksityisviestejä toisille käyttäjille."
#: plugin.py:45
#, fuzzy
msgid ""
"\n"
" This plugin allows users to act through the bot anonymously. The 'do'\n"
" command has the bot perform an anonymous action in a given channel, and\n"
" the 'say' command allows other people to speak through the bot. Since\n"
" this can be fairly well abused, you might want to set\n"
" supybot.plugins.Anonymous.requireCapability so only users with that\n"
" capability can use this plugin. For extra security, you can require "
"that\n"
" the user be *in* the channel they are trying to address anonymously "
"with\n"
" supybot.plugins.Anonymous.requirePresenceInChannel, or you can require\n"
" that the user be registered by setting\n"
" supybot.plugins.Anonymous.requireRegistration.\n"
"\n"
" Example: Proving that you are the owner\n"
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" When you ask for cloak/vhost for your bot, the network operators will\n"
" often ask you to prove that you own the bot. You can do this for "
"example\n"
" with the following method::\n"
"\n"
" @load Anonymous\n"
" @config plugins.anonymous.requirecapability owner\n"
" @config plugins.anonymous.allowprivatetarget True\n"
" @anonymous say <operator nick> Hi, my owner is <your nick> :)\n"
"\n"
" This\n"
" * Loads the plugin.\n"
" * Makes the plugin require that you are the owner\n"
"\n"
" * If anyone could send private messages as the bot, they could also\n"
" access network services.\n"
"\n"
" * Allows sending private messages\n"
" * Sends message ``Hi, my owner is <your nick> :)`` to ``operator "
"nick``.\n"
"\n"
" * Note that you won't see the messages that are sent to the bot.\n"
"\n"
" "
msgstr ""
"Tämä lisäosa sallii käyttäjien toimia botin kautta tuntemattomasti.\n"
" Komento 'do' sallii botin tehdä tuntemattoman toiminnon annetulla "
"kanavalla ja\n"
" komento 'say' sallii toisten ihmisten puhua botin läpi. Koska\n"
" tätä voidaan väärinkäyttää helposti voit tahtoa asettaa asetuksen\n"
" supybot.plugins.Anonymous.requireCapability niin, että vain käyttäjät "
"tuolla\n"
" valtuudella voivat käyttää tätä lisäosaa. Lisäturvallisuuden vuoksi voit "
"vaatia, että käyttäjien täytyy *olla* kanavilla joita he yrittävät puhutella "
"tuntemattomasti asetuksella supybot.plugins.Anonymous."
"requirePresenceInChannel, tai sinä voit vaatia,\n"
" että tuo käyttäjä on rekisteröitynyt asetuksella\n"
" supybot.plugins.Anonymous.requireRegistration"
#: plugin.py:98
msgid "You must be in %s to %q in there."
msgstr "Sinun täytyy olla kanavalla %s %q sinne."
#: plugin.py:102
msgid "I'm lobotomized in %s."
msgstr "Minut on lobotomoitu kanavalla %s."
#: plugin.py:105
msgid ""
"That channel has set its capabilities so as to disallow the use of this "
"plugin."
msgstr "Tuo kanava on asettanut valtuudet kieltämään tämän Pluginin käytön."
#: plugin.py:108
msgid ""
"This command is disabled (supybot.plugins.Anonymous.allowPrivateTarget is "
"False)."
msgstr ""
"Tämä komento on poistettu käytöstä (supybot.plugins.Anonymous."
"allowPrivateTarget on False)."
#: plugin.py:112
msgid ""
"<channel> <text>\n"
"\n"
" Sends <text> to <channel>.\n"
" "
msgstr ""
"<kanava> <teksti>\n"
" Lähettää <tesktin> <kanavalle>."
#: plugin.py:124
msgid ""
"<nick> <text>\n"
"\n"
" Sends <text> to <nick>. Can only be used if\n"
" supybot.plugins.Anonymous.allowPrivateTarget is True.\n"
" "
msgstr ""
"<kanava> <teksti>\n"
"\n"
" Lähettää <tekstin> <nimimerkille>. <Nimimerkille> voidaan lähettää\n"
" viestejä vain asetusarvon supybot.plugins.Anonymous.allowPrivateTarget\n"
" ollessa True.\n"
" "
#: plugin.py:137
msgid ""
"<channel> <action>\n"
"\n"
" Performs <action> in <channel>.\n"
" "
msgstr ""
"<kanava> <toiminto>\n"
"\n"
"Suorittaa <toiminnon> <kanavalla>.\n"
" "
#: plugin.py:148
msgid ""
"<channel> <reaction> <nick>\n"
"\n"
" Sends the <reaction> to <nick>'s last message.\n"
" <reaction> is typically a smiley or an emoji.\n"
"\n"
" This may not be supported on the current network, as this\n"
" command depends on IRCv3 features.\n"
" This is also not supported if\n"
" supybot.protocols.irc.experimentalExtensions disabled\n"
" (don't enable it unless you know what you are doing).\n"
" "
msgstr ""
#: plugin.py:162
msgid ""
"Unable to react, supybot.protocols.irc.experimentalExtensions is disabled."
msgstr ""
#: plugin.py:167
msgid "Unable to react, the network does not support message-tags."
msgstr ""
#: plugin.py:172
msgid ""
"Unable to react, the network does not allow draft/reply and/or draft/react."
msgstr ""
#: plugin.py:181
msgid "I couldn't find a message from %s in my history of %s messages."
msgstr ""
#: plugin.py:189
msgid "Unable to react, %s's last message does not have a message id."
msgstr ""
#~ msgid "%q cannot be used to send private messages."
#~ msgstr "%q:ta ei voi käyttää yksityisviestien lähettämiseen."
#~ msgid ""
#~ "<channel> <text>\n"
#~ "\n"
#~ " Sends <text> to <channel>. Can only send to <nick> if\n"
#~ " supybot.plugins.Anonymous.allowPrivateTarget is True.\n"
#~ " "
#~ msgstr ""
#~ "<kanava> <teksti>\n"
#~ "\n"
#~ " Lähettää <tekstin> <kanavalle>. <Nimimerkille> voidaan lähettää "
#~ "viestejä vain \n"
#~ " asetusarvon supybot.plugins.Anonymous.allowPrivateTarget ollessa "
#~ "True.\n"
#~ " "

View File

@ -1,195 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: Valentin Lorentz <progval@gmail.com>\n"
"Language-Team: Limnoria <progval@gmail.com>\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Français\n"
"X-Poedit-Country: France\n"
"X-Poedit-SourceCharset: ASCII\n"
#: config.py:50
msgid ""
"Determines whether\n"
" the bot should require people trying to use this plugin to be in the\n"
" channel they wish to anonymously send to."
msgstr ""
"Détermine si le bot requiérera que les gens soient sur le canal pour y "
"envoyer des messages anonymement."
#: config.py:54
msgid ""
"Determines whether the bot should require\n"
" people trying to use this plugin to be registered."
msgstr ""
"Détermine si le bot requiérera que les personnes utilisant ce plugin soient "
"enregistrées."
#: config.py:57
msgid ""
"Determines what capability (if any) the bot should\n"
" require people trying to use this plugin to have."
msgstr ""
"Détermine quelle capacité (s'il y en a une) le bot requiéra que les gens "
"utilisant ce plugin aient."
#: config.py:60
#, fuzzy
msgid ""
"Determines whether the bot will allow the\n"
" \"tell\" command to be used. If true, the bot will allow the \"tell\"\n"
" command to send private messages to other users."
msgstr ""
"Détermine si le bot requiérera que les cibles de la commande \"say\" soient "
"publiques (c'est à dire des canaux). Si c'est True, le bot autorisera les "
"personnes à utiliser la commande \"say\" pour envoyer des messages à "
"d'autres utilisateurs en privé."
#: plugin.py:45
msgid ""
"\n"
" This plugin allows users to act through the bot anonymously. The 'do'\n"
" command has the bot perform an anonymous action in a given channel, and\n"
" the 'say' command allows other people to speak through the bot. Since\n"
" this can be fairly well abused, you might want to set\n"
" supybot.plugins.Anonymous.requireCapability so only users with that\n"
" capability can use this plugin. For extra security, you can require "
"that\n"
" the user be *in* the channel they are trying to address anonymously "
"with\n"
" supybot.plugins.Anonymous.requirePresenceInChannel, or you can require\n"
" that the user be registered by setting\n"
" supybot.plugins.Anonymous.requireRegistration.\n"
"\n"
" Example: Proving that you are the owner\n"
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" When you ask for cloak/vhost for your bot, the network operators will\n"
" often ask you to prove that you own the bot. You can do this for "
"example\n"
" with the following method::\n"
"\n"
" @load Anonymous\n"
" @config plugins.anonymous.requirecapability owner\n"
" @config plugins.anonymous.allowprivatetarget True\n"
" @anonymous say <operator nick> Hi, my owner is <your nick> :)\n"
"\n"
" This\n"
" * Loads the plugin.\n"
" * Makes the plugin require that you are the owner\n"
"\n"
" * If anyone could send private messages as the bot, they could also\n"
" access network services.\n"
"\n"
" * Allows sending private messages\n"
" * Sends message ``Hi, my owner is <your nick> :)`` to ``operator "
"nick``.\n"
"\n"
" * Note that you won't see the messages that are sent to the bot.\n"
"\n"
" "
msgstr ""
#: plugin.py:98
msgid "You must be in %s to %q in there."
msgstr "Vous devez être sur %s pour y utiliser %q."
#: plugin.py:102
msgid "I'm lobotomized in %s."
msgstr "Je suis lobotomisé sur %s."
#: plugin.py:105
msgid ""
"That channel has set its capabilities so as to disallow the use of this "
"plugin."
msgstr ""
"Ce canal a définit ses capacités de façon à désactiver l'utilisation de ce "
"plugin."
#: plugin.py:108
msgid ""
"This command is disabled (supybot.plugins.Anonymous.allowPrivateTarget is "
"False)."
msgstr ""
#: plugin.py:112
#, fuzzy
msgid ""
"<channel> <text>\n"
"\n"
" Sends <text> to <channel>.\n"
" "
msgstr ""
"<canal> <action>\n"
"\n"
"Effectue l'<action> sur le <canal>."
#: plugin.py:124
#, fuzzy
msgid ""
"<nick> <text>\n"
"\n"
" Sends <text> to <nick>. Can only be used if\n"
" supybot.plugins.Anonymous.allowPrivateTarget is True.\n"
" "
msgstr ""
"<canal|nick> <text>\n"
"\n"
"Envoie le <texte> au <canal|nick>. Vous ne pouvez envoyer à <nick> que si "
"supybot.plugins.Anonymous.allowPrivateTarget vaut True."
#: plugin.py:137
msgid ""
"<channel> <action>\n"
"\n"
" Performs <action> in <channel>.\n"
" "
msgstr ""
"<canal> <action>\n"
"\n"
"Effectue l'<action> sur le <canal>."
#: plugin.py:148
msgid ""
"<channel> <reaction> <nick>\n"
"\n"
" Sends the <reaction> to <nick>'s last message.\n"
" <reaction> is typically a smiley or an emoji.\n"
"\n"
" This may not be supported on the current network, as this\n"
" command depends on IRCv3 features.\n"
" This is also not supported if\n"
" supybot.protocols.irc.experimentalExtensions disabled\n"
" (don't enable it unless you know what you are doing).\n"
" "
msgstr ""
#: plugin.py:162
msgid ""
"Unable to react, supybot.protocols.irc.experimentalExtensions is disabled."
msgstr ""
#: plugin.py:167
msgid "Unable to react, the network does not support message-tags."
msgstr ""
#: plugin.py:172
msgid ""
"Unable to react, the network does not allow draft/reply and/or draft/react."
msgstr ""
#: plugin.py:181
msgid "I couldn't find a message from %s in my history of %s messages."
msgstr ""
#: plugin.py:189
msgid "Unable to react, %s's last message does not have a message id."
msgstr ""
#~ msgid "%q cannot be used to send private messages."
#~ msgstr "%q ne peut pas être utilisé pour envoyer des messages privés."

View File

@ -1,208 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: Limnoria Anonymous\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2011-07-21 17:32+0100\n"
"Last-Translator: nyuszika7h <litemininyuszika@gmail.com>\n"
"Language-Team: \n"
"Language: hu_HU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: config.py:50
msgid ""
"Determines whether\n"
" the bot should require people trying to use this plugin to be in the\n"
" channel they wish to anonymously send to."
msgstr ""
"Meghatározza, hogy a bot megkövetelje-e, hogy a bővítményt használni kívánó "
"emberek abban a csatornában legyenek, ahová névtelenül szeretnének küldeni."
#: config.py:54
msgid ""
"Determines whether the bot should require\n"
" people trying to use this plugin to be registered."
msgstr ""
"Meghatározza, hogy a bot megkövetelje-e, hogy a bővítményt használni kívánó "
"emberek regisztrálva legyenek."
#: config.py:57
msgid ""
"Determines what capability (if any) the bot should\n"
" require people trying to use this plugin to have."
msgstr ""
"Meghatározza, hogy milyen képesség (ha van ilyen) legyen szükséges a "
"bővítmény használatához."
#: config.py:60
#, fuzzy
msgid ""
"Determines whether the bot will allow the\n"
" \"tell\" command to be used. If true, the bot will allow the \"tell\"\n"
" command to send private messages to other users."
msgstr ""
"Meghatározza, hogy a bot megkövetelje-e, hogy a \"say\" parancs célja "
"publikus legyen (pl., csatornák). Ha ez True, a bot megengedi az embereknek, "
"hogy a \"say\" paranccsal privát üzenetet küldjenek másoknak."
#: plugin.py:45
#, fuzzy
msgid ""
"\n"
" This plugin allows users to act through the bot anonymously. The 'do'\n"
" command has the bot perform an anonymous action in a given channel, and\n"
" the 'say' command allows other people to speak through the bot. Since\n"
" this can be fairly well abused, you might want to set\n"
" supybot.plugins.Anonymous.requireCapability so only users with that\n"
" capability can use this plugin. For extra security, you can require "
"that\n"
" the user be *in* the channel they are trying to address anonymously "
"with\n"
" supybot.plugins.Anonymous.requirePresenceInChannel, or you can require\n"
" that the user be registered by setting\n"
" supybot.plugins.Anonymous.requireRegistration.\n"
"\n"
" Example: Proving that you are the owner\n"
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" When you ask for cloak/vhost for your bot, the network operators will\n"
" often ask you to prove that you own the bot. You can do this for "
"example\n"
" with the following method::\n"
"\n"
" @load Anonymous\n"
" @config plugins.anonymous.requirecapability owner\n"
" @config plugins.anonymous.allowprivatetarget True\n"
" @anonymous say <operator nick> Hi, my owner is <your nick> :)\n"
"\n"
" This\n"
" * Loads the plugin.\n"
" * Makes the plugin require that you are the owner\n"
"\n"
" * If anyone could send private messages as the bot, they could also\n"
" access network services.\n"
"\n"
" * Allows sending private messages\n"
" * Sends message ``Hi, my owner is <your nick> :)`` to ``operator "
"nick``.\n"
"\n"
" * Note that you won't see the messages that are sent to the bot.\n"
"\n"
" "
msgstr ""
"Ez a bővítmény megengedi a felhasználóknak, hogy névtelenül cselekedjenek a "
"boton keresztül. A 'do' parancs hatására a bot végrehajt egy névtelen "
"tevékenységet egy megadott csatornában, és a 'say' parancs megengedi "
"másoknak, hogy a boton keresztül beszéljenek. Mivel ezzel elég könnyen "
"vissza lehet élni, érdemes beállítani a supybot.plugins.Anonymous."
"requireCapability-t, hogy csak az adott képességgel rendelkező felhasználók "
"használhassák ezt a bővítményt. Extra biztonságért a supybot.plugins."
"Anonymous.requirePresenceInChannel-lel megkövetelheted, hogy a felhasználó "
"abban a csatornában legyen, amelyet névtelenül szeretnének megcímezni, vagy "
"a supybot.plugins.Anonymous.requireRegistration-nel megkövetelheted, hogy a "
"felhasználó regisztálva legyen."
#: plugin.py:98
msgid "You must be in %s to %q in there."
msgstr "%s-ban kell lenned, hogy a %q parancsot használd ott."
#: plugin.py:102
msgid "I'm lobotomized in %s."
msgstr "Némítva vagyok %s-ban."
#: plugin.py:105
msgid ""
"That channel has set its capabilities so as to disallow the use of this "
"plugin."
msgstr ""
"A megadott csatornában nem használhatod a bővítményt a csatorna képességei "
"miatt."
#: plugin.py:108
msgid ""
"This command is disabled (supybot.plugins.Anonymous.allowPrivateTarget is "
"False)."
msgstr ""
#: plugin.py:112
#, fuzzy
msgid ""
"<channel> <text>\n"
"\n"
" Sends <text> to <channel>.\n"
" "
msgstr ""
"<csatorna> <tevékenység>\n"
"\n"
"Végrehajtja <tevékenység>-et <csatorna>-ban."
#: plugin.py:124
#, fuzzy
msgid ""
"<nick> <text>\n"
"\n"
" Sends <text> to <nick>. Can only be used if\n"
" supybot.plugins.Anonymous.allowPrivateTarget is True.\n"
" "
msgstr ""
"<csatorna|név> <szöveg>\n"
"\n"
"Elküldi <szöveg>-et <csatorna|név>-nek. Csak akkor küldhet <név>-nek, ha a "
"supybot.plugins.Anonymous.allowPrivateTarget True."
#: plugin.py:137
msgid ""
"<channel> <action>\n"
"\n"
" Performs <action> in <channel>.\n"
" "
msgstr ""
"<csatorna> <tevékenység>\n"
"\n"
"Végrehajtja <tevékenység>-et <csatorna>-ban."
#: plugin.py:148
msgid ""
"<channel> <reaction> <nick>\n"
"\n"
" Sends the <reaction> to <nick>'s last message.\n"
" <reaction> is typically a smiley or an emoji.\n"
"\n"
" This may not be supported on the current network, as this\n"
" command depends on IRCv3 features.\n"
" This is also not supported if\n"
" supybot.protocols.irc.experimentalExtensions disabled\n"
" (don't enable it unless you know what you are doing).\n"
" "
msgstr ""
#: plugin.py:162
msgid ""
"Unable to react, supybot.protocols.irc.experimentalExtensions is disabled."
msgstr ""
#: plugin.py:167
msgid "Unable to react, the network does not support message-tags."
msgstr ""
#: plugin.py:172
msgid ""
"Unable to react, the network does not allow draft/reply and/or draft/react."
msgstr ""
#: plugin.py:181
msgid "I couldn't find a message from %s in my history of %s messages."
msgstr ""
#: plugin.py:189
msgid "Unable to react, %s's last message does not have a message id."
msgstr ""
#~ msgid "%q cannot be used to send private messages."
#~ msgstr "A %q parancs nem használható privát üzenetek küldésére."

View File

@ -1,212 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2011-08-10 00:13+0200\n"
"Last-Translator: skizzhg <skizzhg@gmx.com>\n"
"Language-Team: Italian <skizzhg@gmx.com>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: config.py:50
msgid ""
"Determines whether\n"
" the bot should require people trying to use this plugin to be in the\n"
" channel they wish to anonymously send to."
msgstr ""
"Determina se il bot richieda che gli utenti siano in canale\n"
" per inviare messaggi in forma anonima."
#: config.py:54
msgid ""
"Determines whether the bot should require\n"
" people trying to use this plugin to be registered."
msgstr ""
"Determina se il bot richieda che gli utenti siano registrati\n"
" per usare il plugin."
#: config.py:57
msgid ""
"Determines what capability (if any) the bot should\n"
" require people trying to use this plugin to have."
msgstr ""
"Determina quali capacità (eventuali) debbano\n"
" avere gli utenti per utilizzare questo plugin."
#: config.py:60
#, fuzzy
msgid ""
"Determines whether the bot will allow the\n"
" \"tell\" command to be used. If true, the bot will allow the \"tell\"\n"
" command to send private messages to other users."
msgstr ""
"Determina se il bot richiederà che le destinazioni del comando \"say\" "
"siano\n"
" pubbliche (ovvero i canali). Se impostato a True, il bot permetterà\n"
" di usare il comando \"say\" per inviare messaggi privati ad altri utenti."
#: plugin.py:45
#, fuzzy
msgid ""
"\n"
" This plugin allows users to act through the bot anonymously. The 'do'\n"
" command has the bot perform an anonymous action in a given channel, and\n"
" the 'say' command allows other people to speak through the bot. Since\n"
" this can be fairly well abused, you might want to set\n"
" supybot.plugins.Anonymous.requireCapability so only users with that\n"
" capability can use this plugin. For extra security, you can require "
"that\n"
" the user be *in* the channel they are trying to address anonymously "
"with\n"
" supybot.plugins.Anonymous.requirePresenceInChannel, or you can require\n"
" that the user be registered by setting\n"
" supybot.plugins.Anonymous.requireRegistration.\n"
"\n"
" Example: Proving that you are the owner\n"
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" When you ask for cloak/vhost for your bot, the network operators will\n"
" often ask you to prove that you own the bot. You can do this for "
"example\n"
" with the following method::\n"
"\n"
" @load Anonymous\n"
" @config plugins.anonymous.requirecapability owner\n"
" @config plugins.anonymous.allowprivatetarget True\n"
" @anonymous say <operator nick> Hi, my owner is <your nick> :)\n"
"\n"
" This\n"
" * Loads the plugin.\n"
" * Makes the plugin require that you are the owner\n"
"\n"
" * If anyone could send private messages as the bot, they could also\n"
" access network services.\n"
"\n"
" * Allows sending private messages\n"
" * Sends message ``Hi, my owner is <your nick> :)`` to ``operator "
"nick``.\n"
"\n"
" * Note that you won't see the messages that are sent to the bot.\n"
"\n"
" "
msgstr ""
"Questo plugin permette agli utenti di agire attraverso il bot in modo "
"anonimo.\n"
" Il comando \"do\" esegue un'azione anonima in un dato canale, mentre "
"\"say\"\n"
" permette di parlare tramite il bot. Giacché si può facilmente abusarne, "
"è\n"
" possibile impostare supybot.plugins.Anonymous.requireCapability in modo "
"che\n"
" solo gli utenti con determinate capacità possano usare il plugin. Per "
"una\n"
" maggiore sicurezza è ppossibile richiedere con supybot.plugins.Anonymous."
"requirePresenceInChannel\n"
" che l'utente intenzionato a parlare anonimamente sia in canale; o anche, "
"tramite\n"
" supybot.plugins.Anonymous.requireRegistration, che l'utente sia "
"registrato. "
#: plugin.py:98
msgid "You must be in %s to %q in there."
msgstr "Devi essere in %s per %q."
#: plugin.py:102
msgid "I'm lobotomized in %s."
msgstr "In %s sono lobotomizzato."
#: plugin.py:105
msgid ""
"That channel has set its capabilities so as to disallow the use of this "
"plugin."
msgstr ""
"Questo canale ha le capacità impostate in modo da impedire l'utilizzo di "
"questo plugin."
#: plugin.py:108
msgid ""
"This command is disabled (supybot.plugins.Anonymous.allowPrivateTarget is "
"False)."
msgstr ""
#: plugin.py:112
#, fuzzy
msgid ""
"<channel> <text>\n"
"\n"
" Sends <text> to <channel>.\n"
" "
msgstr ""
"<canale> <azione>\n"
"\n"
" Esegue <azione> in <canale>.\n"
" "
#: plugin.py:124
#, fuzzy
msgid ""
"<nick> <text>\n"
"\n"
" Sends <text> to <nick>. Can only be used if\n"
" supybot.plugins.Anonymous.allowPrivateTarget is True.\n"
" "
msgstr ""
"<canale|nick> <testo>\n"
"\n"
" Invia <testo> a <canale|nick>. Può solo inviare a <nick> se\n"
" supybot.plugins.Anonymous.allowPrivateTarget è impostato a True.\n"
" "
#: plugin.py:137
msgid ""
"<channel> <action>\n"
"\n"
" Performs <action> in <channel>.\n"
" "
msgstr ""
"<canale> <azione>\n"
"\n"
" Esegue <azione> in <canale>.\n"
" "
#: plugin.py:148
msgid ""
"<channel> <reaction> <nick>\n"
"\n"
" Sends the <reaction> to <nick>'s last message.\n"
" <reaction> is typically a smiley or an emoji.\n"
"\n"
" This may not be supported on the current network, as this\n"
" command depends on IRCv3 features.\n"
" This is also not supported if\n"
" supybot.protocols.irc.experimentalExtensions disabled\n"
" (don't enable it unless you know what you are doing).\n"
" "
msgstr ""
#: plugin.py:162
msgid ""
"Unable to react, supybot.protocols.irc.experimentalExtensions is disabled."
msgstr ""
#: plugin.py:167
msgid "Unable to react, the network does not support message-tags."
msgstr ""
#: plugin.py:172
msgid ""
"Unable to react, the network does not allow draft/reply and/or draft/react."
msgstr ""
#: plugin.py:181
msgid "I couldn't find a message from %s in my history of %s messages."
msgstr ""
#: plugin.py:189
msgid "Unable to react, %s's last message does not have a message id."
msgstr ""
#~ msgid "%q cannot be used to send private messages."
#~ msgstr "%q non può essere usato per inviare messaggi privati."

View File

@ -1,165 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: config.py:50
msgid ""
"Determines whether\n"
" the bot should require people trying to use this plugin to be in the\n"
" channel they wish to anonymously send to."
msgstr ""
#: config.py:54
msgid ""
"Determines whether the bot should require\n"
" people trying to use this plugin to be registered."
msgstr ""
#: config.py:57
msgid ""
"Determines what capability (if any) the bot should\n"
" require people trying to use this plugin to have."
msgstr ""
#: config.py:60
msgid ""
"Determines whether the bot will allow the\n"
" \"tell\" command to be used. If true, the bot will allow the \"tell\"\n"
" command to send private messages to other users."
msgstr ""
#: plugin.py:45
#, docstring
msgid ""
"\n"
" This plugin allows users to act through the bot anonymously. The 'do'\n"
" command has the bot perform an anonymous action in a given channel, and\n"
" the 'say' command allows other people to speak through the bot. Since\n"
" this can be fairly well abused, you might want to set\n"
" supybot.plugins.Anonymous.requireCapability so only users with that\n"
" capability can use this plugin. For extra security, you can require that\n"
" the user be *in* the channel they are trying to address anonymously with\n"
" supybot.plugins.Anonymous.requirePresenceInChannel, or you can require\n"
" that the user be registered by setting\n"
" supybot.plugins.Anonymous.requireRegistration.\n"
"\n"
" Example: Proving that you are the owner\n"
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
"\n"
" When you ask for cloak/vhost for your bot, the network operators will\n"
" often ask you to prove that you own the bot. You can do this for example\n"
" with the following method::\n"
"\n"
" @load Anonymous\n"
" @config plugins.anonymous.requirecapability owner\n"
" @config plugins.anonymous.allowprivatetarget True\n"
" @anonymous say <operator nick> Hi, my owner is <your nick> :)\n"
"\n"
" This\n"
" * Loads the plugin.\n"
" * Makes the plugin require that you are the owner\n"
"\n"
" * If anyone could send private messages as the bot, they could also\n"
" access network services.\n"
"\n"
" * Allows sending private messages\n"
" * Sends message ``Hi, my owner is <your nick> :)`` to ``operator nick``.\n"
"\n"
" * Note that you won't see the messages that are sent to the bot.\n"
"\n"
" "
msgstr ""
#: plugin.py:98
msgid "You must be in %s to %q in there."
msgstr ""
#: plugin.py:102
msgid "I'm lobotomized in %s."
msgstr ""
#: plugin.py:105
msgid "That channel has set its capabilities so as to disallow the use of this plugin."
msgstr ""
#: plugin.py:108
msgid "This command is disabled (supybot.plugins.Anonymous.allowPrivateTarget is False)."
msgstr ""
#: plugin.py:112
#, docstring
msgid ""
"<channel> <text>\n"
"\n"
" Sends <text> to <channel>.\n"
" "
msgstr ""
#: plugin.py:124
#, docstring
msgid ""
"<nick> <text>\n"
"\n"
" Sends <text> to <nick>. Can only be used if\n"
" supybot.plugins.Anonymous.allowPrivateTarget is True.\n"
" "
msgstr ""
#: plugin.py:137
#, docstring
msgid ""
"<channel> <action>\n"
"\n"
" Performs <action> in <channel>.\n"
" "
msgstr ""
#: plugin.py:148
#, docstring
msgid ""
"<channel> <reaction> <nick>\n"
"\n"
" Sends the <reaction> to <nick>'s last message.\n"
" <reaction> is typically a smiley or an emoji.\n"
"\n"
" This may not be supported on the current network, as this\n"
" command depends on IRCv3 features.\n"
" This is also not supported if\n"
" supybot.protocols.irc.experimentalExtensions disabled\n"
" (don't enable it unless you know what you are doing).\n"
" "
msgstr ""
#: plugin.py:162
msgid "Unable to react, supybot.protocols.irc.experimentalExtensions is disabled."
msgstr ""
#: plugin.py:167
msgid "Unable to react, the network does not support message-tags."
msgstr ""
#: plugin.py:172
msgid "Unable to react, the network does not allow draft/reply and/or draft/react."
msgstr ""
#: plugin.py:181
msgid "I couldn't find a message from %s in my history of %s messages."
msgstr ""
#: plugin.py:189
msgid "Unable to react, %s's last message does not have a message id."
msgstr ""

View File

@ -1,214 +0,0 @@
###
# Copyright (c) 2005, Daniel DiPaolo
# Copyright (c) 2014, James McCoy
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import functools
import supybot.conf as conf
import supybot.ircdb as ircdb
import supybot.utils as utils
from supybot.commands import *
import supybot.ircmsgs as ircmsgs
import supybot.callbacks as callbacks
import supybot.ircutils as ircutils
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Anonymous')
class Anonymous(callbacks.Plugin):
"""
This plugin allows users to act through the bot anonymously. The 'do'
command has the bot perform an anonymous action in a given channel, and
the 'say' command allows other people to speak through the bot. Since
this can be fairly well abused, you might want to set
supybot.plugins.Anonymous.requireCapability so only users with that
capability can use this plugin. For extra security, you can require that
the user be *in* the channel they are trying to address anonymously with
supybot.plugins.Anonymous.requirePresenceInChannel, or you can require
that the user be registered by setting
supybot.plugins.Anonymous.requireRegistration.
Example: Proving that you are the owner
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When you ask for cloak/vhost for your bot, the network operators will
often ask you to prove that you own the bot. You can do this for example
with the following method::
@load Anonymous
@config plugins.anonymous.requirecapability owner
@config plugins.anonymous.allowprivatetarget True
@anonymous say <operator nick> Hi, my owner is <your nick> :)
This
* Loads the plugin.
* Makes the plugin require that you are the owner
* If anyone could send private messages as the bot, they could also
access network services.
* Allows sending private messages
* Sends message ``Hi, my owner is <your nick> :)`` to ``operator nick``.
* Note that you won't see the messages that are sent to the bot.
"""
def _preCheck(self, irc, msg, target, action):
if self.registryValue('requireRegistration', target, irc.network):
try:
foo = ircdb.users.getUser(msg.prefix)
except KeyError:
irc.errorNotRegistered(Raise=True)
capability = self.registryValue('requireCapability',
target, irc.network)
if capability:
if not ircdb.checkCapability(msg.prefix, capability):
irc.errorNoCapability(capability, Raise=True)
if action != 'tell':
require_presence = self.registryValue('requirePresenceInChannel',
target, irc.network)
if require_presence and \
msg.nick not in irc.state.channels[target].users:
irc.error(format(_('You must be in %s to %q in there.'),
target, action), Raise=True)
c = ircdb.channels.getChannel(target)
if c.lobotomized:
irc.error(format(_('I\'m lobotomized in %s.'), target),
Raise=True)
if not c._checkCapability(self.name()):
irc.error(_('That channel has set its capabilities so as to '
'disallow the use of this plugin.'), Raise=True)
elif not self.registryValue('allowPrivateTarget'):
irc.error(_('This command is disabled (supybot.plugins.Anonymous.'
'allowPrivateTarget is False).'), Raise=True)
def say(self, irc, msg, args, target, text):
"""<channel> <text>
Sends <text> to <channel>.
"""
self._preCheck(irc, msg, target, 'say')
self.log.info('Saying %q in %s due to %s.',
text, target, msg.prefix)
irc.queueMsg(ircmsgs.privmsg(target, text))
irc.noReply()
say = wrap(say, ['inChannel', 'text'])
def tell(self, irc, msg, args, target, text):
"""<nick> <text>
Sends <text> to <nick>. Can only be used if
supybot.plugins.Anonymous.allowPrivateTarget is True.
"""
self._preCheck(irc, msg, target, 'tell')
self.log.info('Telling %q to %s due to %s.',
text, target, msg.prefix)
irc.queueMsg(ircmsgs.privmsg(target, text))
irc.noReply()
tell = wrap(tell, ['nick', 'text'])
def do(self, irc, msg, args, channel, text):
"""<channel> <action>
Performs <action> in <channel>.
"""
self._preCheck(irc, msg, channel, 'do')
self.log.info('Performing %q in %s due to %s.',
text, channel, msg.prefix)
irc.reply(text, action=True, to=channel)
do = wrap(do, ['inChannel', 'text'])
def react(self, irc, msg, args, channel, reaction, nick):
"""<channel> <reaction> <nick>
Sends the <reaction> to <nick>'s last message.
<reaction> is typically a smiley or an emoji.
This may not be supported on the current network, as this
command depends on IRCv3 features.
This is also not supported if
supybot.protocols.irc.experimentalExtensions disabled
(don't enable it unless you know what you are doing).
"""
self._preCheck(irc, msg, channel, 'react')
if not conf.supybot.protocols.irc.experimentalExtensions():
irc.error(_('Unable to react, '
'supybot.protocols.irc.experimentalExtensions is '
'disabled.'), Raise=True)
if not 'message-tags' in irc.state.capabilities_ack:
irc.error(_('Unable to react, the network does not support '
'message-tags.'), Raise=True)
if irc.state.getClientTagDenied('draft/reply') \
or irc.state.getClientTagDenied('draft/react'):
irc.error(_('Unable to react, the network does not allow '
'draft/reply and/or draft/react.'), Raise=True)
iterable = filter(functools.partial(self._validLastMsg, irc),
reversed(irc.state.history))
for react_to_msg in iterable:
if react_to_msg.nick == nick:
break
else:
irc.error(_('I couldn\'t find a message from %s in '
'my history of %s messages.')
% (nick, len(irc.state.history)),
Raise=True)
react_to_msgid = react_to_msg.server_tags.get('msgid')
if not react_to_msgid:
irc.error(_('Unable to react, %s\'s last message does not have '
'a message id.') % nick, Raise=True)
self.log.info('Reacting with %q in %s due to %s.',
reaction, channel, msg.prefix)
reaction_msg = ircmsgs.IrcMsg(command='TAGMSG', args=(channel,),
server_tags={'+draft/reply': react_to_msgid,
'+draft/react': reaction})
irc.queueMsg(reaction_msg)
react = wrap(
react, ['inChannel', 'somethingWithoutSpaces', 'nickInChannel'])
def _validLastMsg(self, irc, msg):
return msg.prefix and \
msg.command == 'PRIVMSG' and \
msg.channel
Anonymous = internationalizeDocstring(Anonymous)
Class = Anonymous
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,148 +0,0 @@
###
# Copyright (c) 2005, Daniel DiPaolo
# Copyright (c) 2014, James McCoy
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import supybot.conf as conf
from supybot.test import *
class AnonymousTestCase(ChannelPluginTestCase):
plugins = ('Anonymous',)
def testSay(self):
self.assertError('anonymous say %s I love you!' % self.channel)
with conf.supybot.plugins.Anonymous.requireRegistration.context(False):
m = self.assertNotError('anonymous say %s foo!' % self.channel)
self.assertTrue(m.args[1] == 'foo!')
def testTell(self):
self.assertError('anonymous tell %s I love you!' % self.nick)
with conf.supybot.plugins.Anonymous.requireRegistration.context(False):
self.assertError('anonymous tell %s foo!' % self.channel)
with conf.supybot.plugins.Anonymous.allowPrivateTarget.context(True):
m = self.assertNotError('anonymous tell %s foo!' % self.nick)
self.assertTrue(m.args[1] == 'foo!')
def testAction(self):
m = self.assertError('anonymous do %s loves you!' % self.channel)
with conf.supybot.plugins.Anonymous.requireRegistration.context(False):
m = self.assertNotError('anonymous do %s loves you!'%self.channel)
self.assertEqual(m.args, ircmsgs.action(self.channel,
'loves you!').args)
def testReact(self):
with self.subTest('nick not in channel'):
self.assertRegexp('anonymous react :) blah',
'blah is not in %s' % self.channel)
self.irc.feedMsg(ircmsgs.IrcMsg(
':blah!foo@example JOIN %s' % self.channel))
with self.subTest('require registration'):
self.assertRegexp('anonymous react :) blah',
'must be registered')
self.assertIsNone(self.irc.takeMsg())
with conf.supybot.plugins.Anonymous.requireRegistration.context(False):
with self.subTest('experimental extensions disabled'):
self.assertRegexp('anonymous react :) blah',
'protocols.irc.experimentalExtensions is disabled')
self.assertIsNone(self.irc.takeMsg())
with conf.supybot.plugins.Anonymous.requireRegistration.context(False), \
conf.supybot.protocols.irc.experimentalExtensions.context(True):
with self.subTest('server support missing'):
self.assertRegexp('anonymous react :) blah',
'network does not support message-tags')
self.assertIsNone(self.irc.takeMsg())
self.irc.state.capabilities_ack.add('message-tags')
with self.subTest('no message from the target'):
self.assertRegexp('anonymous react :) blah',
'couldn\'t find a message')
self.assertIsNone(self.irc.takeMsg())
self.irc.feedMsg(ircmsgs.IrcMsg(
':blah!foo@example PRIVMSG %s :hello' % self.channel))
with self.subTest('original message not tagged with msgid'):
self.assertRegexp('anonymous react :) blah',
'not have a message id')
self.assertIsNone(self.irc.takeMsg())
self.irc.feedMsg(ircmsgs.IrcMsg(
'@msgid=123 :blah!foo@example PRIVMSG %s :hello'
% self.channel))
# Works
with self.subTest('canonical working case'):
m = self.getMsg('anonymous react :) blah')
self.assertEqual(m, ircmsgs.IrcMsg(
'@+draft/reply=123;+draft/react=:) TAGMSG %s'
% self.channel))
def testReactClienttagdeny(self):
self.irc.feedMsg(ircmsgs.IrcMsg(
':blah!foo@example JOIN %s' % self.channel))
self.irc.feedMsg(ircmsgs.IrcMsg(
'@msgid=123 :blah!foo@example PRIVMSG %s :hello'
% self.channel))
self.irc.state.capabilities_ack.add('message-tags')
with conf.supybot.plugins.Anonymous.requireRegistration.context(False), \
conf.supybot.protocols.irc.experimentalExtensions.context(True):
# Works
self.irc.state.supported['CLIENTTAGDENY'] = 'foo,bar'
for value in ('draft/reply', 'draft/react', '*,-draft/reply',
'*,draft/react'):
self.irc.state.supported['CLIENTTAGDENY'] = value
with self.subTest('denied by CLIENTTAGDENY=%s' % value):
self.assertRegexp('anonymous react :) blah',
'draft/reply and/or draft/react')
self.assertIsNone(self.irc.takeMsg())
# Works
for value in ('foo,bar', '*,-draft/reply,-draft/react'):
self.irc.state.supported['CLIENTTAGDENY'] = value
with self.subTest('allowed by CLIENTTAGDENY=%s' % value):
m = self.getMsg('anonymous react :) blah')
self.assertEqual(m, ircmsgs.IrcMsg(
'@+draft/reply=123;+draft/react=:) TAGMSG %s'
% self.channel))
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,131 +0,0 @@
.. _plugin-AutoMode:
Documentation for the AutoMode plugin for Supybot
=================================================
Purpose
-------
Automatically ops, voices, or halfops, or bans people when they join a channel,
according to their capabilities. If you want your bot automatically op users
when they join your channel, this is the plugin to load.
Usage
-----
This plugin, when configured, allows the bot to automatically set modes
on users when they join.
* if ``plugins.automode.op`` is set to ``True``, users with the
``#channel,op`` capability are opped when they join.
* if ``plugins.automode.halfop`` is set to ``True``, users with the
``#channel,halfop`` are halfopped when they join.
* if ``plugins.automode.voice`` is set to ``True``, users with the
``#channel,voice`` are voiced when they join.
This plugin also kbans people on ``@channel ban list``
(``config plugins.automode.ban``) when they join and if moding users with
lower capability is enabled, that is also applied to users with higher
capability (``config plugins.automode.fallthrough``).
.. _conf-AutoMode:
Configuration
-------------
.. _conf-supybot.plugins.AutoMode.alternativeCapabilities:
supybot.plugins.AutoMode.alternativeCapabilities
This config variable defaults to "True", is network-specific, and is channel-specific.
Determines whether the bot will check for 'alternative capabilities' (ie. autoop, autohalfop, autovoice) in addition to/instead of classic ones.
.. _conf-supybot.plugins.AutoMode.ban:
supybot.plugins.AutoMode.ban
This config variable defaults to "True", is network-specific, and is channel-specific.
Determines whether the bot will automatically ban people who join the channel and are on the banlist.
.. _conf-supybot.plugins.AutoMode.ban.period:
supybot.plugins.AutoMode.ban.period
This config variable defaults to "86400", is network-specific, and is channel-specific.
Determines how many seconds the bot will automatically ban a person when banning.
.. _conf-supybot.plugins.AutoMode.delay:
supybot.plugins.AutoMode.delay
This config variable defaults to "0", is network-specific, and is channel-specific.
Determines how many seconds the bot will wait before applying a mode. Has no effect on bans.
.. _conf-supybot.plugins.AutoMode.enable:
supybot.plugins.AutoMode.enable
This config variable defaults to "True", is network-specific, and is channel-specific.
Determines whether this plugin is enabled.
.. _conf-supybot.plugins.AutoMode.extra:
supybot.plugins.AutoMode.extra
This config variable defaults to " ", is network-specific, and is channel-specific.
Extra modes that will be applied to a user. Example syntax: user1+o-v user2+v user3-v
.. _conf-supybot.plugins.AutoMode.fallthrough:
supybot.plugins.AutoMode.fallthrough
This config variable defaults to "True", is network-specific, and is channel-specific.
Determines whether the bot will "fall through" to halfop/voicing when auto-opping is turned off but auto-halfopping/voicing are turned on.
.. _conf-supybot.plugins.AutoMode.halfop:
supybot.plugins.AutoMode.halfop
This config variable defaults to "False", is network-specific, and is channel-specific.
Determines whether the bot will automatically halfop people with the <channel>,halfop capability when they join the channel.
.. _conf-supybot.plugins.AutoMode.op:
supybot.plugins.AutoMode.op
This config variable defaults to "False", is network-specific, and is channel-specific.
Determines whether the bot will automatically op people with the <channel>,op capability when they join the channel.
.. _conf-supybot.plugins.AutoMode.owner:
supybot.plugins.AutoMode.owner
This config variable defaults to "False", is not network-specific, and is not channel-specific.
Determines whether this plugin will automode owners even if they don't have op/halfop/voice/whatever capability.
.. _conf-supybot.plugins.AutoMode.public:
supybot.plugins.AutoMode.public
This config variable defaults to "True", is not network-specific, and is not channel-specific.
Determines whether this plugin is publicly visible.
.. _conf-supybot.plugins.AutoMode.voice:
supybot.plugins.AutoMode.voice
This config variable defaults to "False", is network-specific, and is channel-specific.
Determines whether the bot will automatically voice people with the <channel>,voice capability when they join the channel.

View File

@ -1,65 +0,0 @@
###
# Copyright (c) 2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
"""
Automatically ops, voices, or halfops, or bans people when they join a channel,
according to their capabilities. If you want your bot automatically op users
when they join your channel, this is the plugin to load.
"""
import supybot
import supybot.world as world
# Use this for the version of this plugin. You may wish to put a CVS keyword
# in here if you're keeping the plugin in CVS or some similar system.
__version__ = "%%VERSION%%"
__author__ = supybot.authors.jemfinch
__maintainer__ = supybot.authors.limnoria_core
# This is a dictionary mapping supybot.Author instances to lists of
# contributions.
__contributors__ = {}
from . import config
from . import plugin
from importlib import reload
reload(plugin) # In case we're being reloaded.
# Add more reloads here if you add third-party modules and want them to be
# reloaded when this plugin is reloaded. Don't forget to import them as well!
if world.testing:
from . import test
Class = plugin.Class
configure = config.configure
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,87 +0,0 @@
###
# Copyright (c) 2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import supybot.conf as conf
import supybot.registry as registry
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('AutoMode')
def configure(advanced):
# This will be called by supybot to configure this module. advanced is
# a bool that specifies whether the user identified themself as an advanced
# user or not. You should effect your configuration by manipulating the
# registry as appropriate.
from supybot.questions import expect, anything, something, yn
conf.registerPlugin('AutoMode', True)
AutoMode = conf.registerPlugin('AutoMode')
conf.registerChannelValue(AutoMode, 'enable',
registry.Boolean(True, _("""Determines whether this plugin is enabled.
""")))
conf.registerGlobalValue(AutoMode, 'owner',
registry.Boolean(False, _("""Determines whether this plugin will automode
owners even if they don't have op/halfop/voice/whatever capability.""")))
conf.registerChannelValue(AutoMode, 'alternativeCapabilities',
registry.Boolean(True, _("""Determines whether the bot will
check for 'alternative capabilities' (ie. autoop, autohalfop,
autovoice) in addition to/instead of classic ones.""")))
conf.registerChannelValue(AutoMode, 'fallthrough',
registry.Boolean(True, _("""Determines whether the bot will "fall
through" to halfop/voicing when auto-opping is turned off but
auto-halfopping/voicing are turned on.""")))
conf.registerChannelValue(AutoMode, 'op',
registry.Boolean(False, _("""Determines whether the bot will automatically
op people with the <channel>,op capability when they join the channel.
""")))
conf.registerChannelValue(AutoMode, 'halfop',
registry.Boolean(False, _("""Determines whether the bot will automatically
halfop people with the <channel>,halfop capability when they join the
channel.""")))
conf.registerChannelValue(AutoMode, 'voice',
registry.Boolean(False, _("""Determines whether the bot will automatically
voice people with the <channel>,voice capability when they join the
channel.""")))
conf.registerChannelValue(AutoMode, 'ban',
registry.Boolean(True, _("""Determines whether the bot will automatically
ban people who join the channel and are on the banlist.""")))
conf.registerChannelValue(AutoMode.ban, 'period',
registry.PositiveInteger(86400, _("""Determines how many seconds the bot
will automatically ban a person when banning.""")))
conf.registerChannelValue(AutoMode, 'delay',
registry.Integer(0, _("""Determines how many seconds the bot will wait
before applying a mode. Has no effect on bans.""")))
conf.registerChannelValue(AutoMode, 'extra',
registry.SpaceSeparatedListOfStrings([], _("""Extra modes that will be
applied to a user. Example syntax: user1+o-v user2+v user3-v""")))
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,128 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Supybot\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2012-04-27 15:38+0200\n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: German <fbesser@gmail.com>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Poedit-Language: German\n"
"X-Poedit-Country: GERMANY\n"
#: config.py:47
msgid ""
"Determines whether this plugin is enabled.\n"
" "
msgstr "Legt fest ob das Plugin aktiv ist."
#: config.py:50
msgid ""
"Determines whether this plugin will automode\n"
" owners even if they don't have op/halfop/voice/whatever capability."
msgstr ""
"Legt fest ob das Plugin Besitzern automatisch den Modus zuweist, obwohl sie "
"nicht die op/halfop/voice/wasauchimmer Fähigkeit besitzen."
#: config.py:53
msgid ""
"Determines whether the bot will\n"
" check for 'alternative capabilities' (ie. autoop, autohalfop,\n"
" autovoice) in addition to/instead of classic ones."
msgstr ""
#: config.py:57
#, fuzzy
msgid ""
"Determines whether the bot will \"fall\n"
" through\" to halfop/voicing when auto-opping is turned off but\n"
" auto-halfopping/voicing are turned on."
msgstr ""
"Legt fest ob der Bot \"zurückfällt\" auf Halboperator/Sprechrechte wenn "
"automatischer Operator abgeschaltet ist, aber automatische Halboperator/"
"Sprecherechte angeschaltet sind."
#: config.py:61
msgid ""
"Determines whether the bot will automatically\n"
" op people with the <channel>,op capability when they join the channel.\n"
" "
msgstr ""
"Legt fest ob der Bot Personen, mit der <Kanal>,op Fähigkeit, automatisch "
"Operatorrechte zuweisen soll, wenn sie den Kanal betreten."
#: config.py:65
msgid ""
"Determines whether the bot will automatically\n"
" halfop people with the <channel>,halfop capability when they join the\n"
" channel."
msgstr ""
"Legt fest ob der Bot Personen, mit der <Kanal>,halfop Fähigkeit, automatisch "
"Halboperatorrechte zuweisen soll, wenn sie den Kanal betreten."
#: config.py:69
msgid ""
"Determines whether the bot will automatically\n"
" voice people with the <channel>,voice capability when they join the\n"
" channel."
msgstr ""
"Legt fest ob der Bot Personen, mit der <Kanal>,voice Fähigkeit, automatisch "
"Sprechrechte zuweisen soll, wenn sie den Kanal betreten."
#: config.py:73
msgid ""
"Determines whether the bot will automatically\n"
" ban people who join the channel and are on the banlist."
msgstr ""
"Legt fest ob der Bot automatisch Personen bannen soll die auf der Banliste "
"stehen."
#: config.py:76
msgid ""
"Determines how many seconds the bot\n"
" will automatically ban a person when banning."
msgstr "Legt fest wieviele Sekunden der Bot Personen automatisch bannt."
#: config.py:80
#, fuzzy
msgid ""
"Determines how many seconds the bot will wait\n"
" before applying a mode. Has no effect on bans."
msgstr "Legt fest wieviele Sekunden der Bot Personen automatisch bannt."
#: config.py:84
msgid ""
"Extra modes that will be\n"
" applied to a user. Example syntax: user1+o-v user2+v user3-v"
msgstr ""
#: plugin.py:49
msgid ""
"\n"
" This plugin, when configured, allows the bot to automatically set modes\n"
" on users when they join.\n"
"\n"
" * if ``plugins.automode.op`` is set to ``True``, users with the\n"
" ``#channel,op`` capability are opped when they join.\n"
" * if ``plugins.automode.halfop`` is set to ``True``, users with the\n"
" ``#channel,halfop`` are halfopped when they join.\n"
" * if ``plugins.automode.voice`` is set to ``True``, users with the\n"
" ``#channel,voice`` are voiced when they join.\n"
"\n"
" This plugin also kbans people on ``@channel ban list``\n"
" (``config plugins.automode.ban``) when they join and if moding users "
"with\n"
" lower capability is enabled, that is also applied to users with higher\n"
" capability (``config plugins.automode.fallthrough``).\n"
"\n"
" "
msgstr ""
#: plugin.py:97
msgid ""
"Determines whether or not a mode has already\n"
" been applied."
msgstr ""

View File

@ -1,152 +0,0 @@
# AutoMode plugin in Limnoria.
# Copyright (C) 2011, 2012 Limnoria
# Mikaela Suomalainen <mkaysi@outlook.com>, 2011, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: Supybot AutoMode\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2014-12-20 11:38+0200\n"
"Last-Translator: Mikaela Suomalainen <mikaela.suomalainen@outlook.com>\n"
"Language-Team: suomi <>\n"
"Language: fi_FI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: \n"
"X-Generator: Poedit 1.6.10\n"
#: config.py:47
msgid ""
"Determines whether this plugin is enabled.\n"
" "
msgstr "Määrittää onko tämä lisäosa käytössä."
#: config.py:50
msgid ""
"Determines whether this plugin will automode\n"
" owners even if they don't have op/halfop/voice/whatever capability."
msgstr ""
"Määrittää vaihtaako botti omistajien tilaa automaattisesti, vaikka heillä ei "
"olisi\n"
" op/halfop/voice/ihansama valtuutta."
#: config.py:53
msgid ""
"Determines whether the bot will\n"
" check for 'alternative capabilities' (ie. autoop, autohalfop,\n"
" autovoice) in addition to/instead of classic ones."
msgstr ""
"Määrittää tarkistaako botti 'vaihtoehtoisten valtuuksien' varalta (esim. "
"autoop,\n"
" autohalfop, autovoice) klassisten lisäksi/sijaan."
#: config.py:57
msgid ""
"Determines whether the bot will \"fall\n"
" through\" to halfop/voicing when auto-opping is turned off but\n"
" auto-halfopping/voicing are turned on."
msgstr ""
"Määrittää \"alentuuko\" botti halfoppaamiseen/voicen antamiseen kun "
"automaattinen\n"
" oprtaattori aseman antaminen on poistettu käytöstä, mutta automaattinen\n"
" puolioperaattori aseman/äänen antaminen on käytössä."
#: config.py:61
msgid ""
"Determines whether the bot will automatically\n"
" op people with the <channel>,op capability when they join the channel.\n"
" "
msgstr ""
"Määrittää oppaako botti\n"
" ihmiset, joilla on #<kanava>,op valtuus automaattisesti, kun he liittyvät "
"kanavalle."
#: config.py:65
msgid ""
"Determines whether the bot will automatically\n"
" halfop people with the <channel>,halfop capability when they join the\n"
" channel."
msgstr ""
"Määrittää antaako botti puolioperaattorin aseman automaattisesti, kun "
"ihmiset, joilla on #<kanava>,halfop valtuus liittyvät kanavalle."
#: config.py:69
msgid ""
"Determines whether the bot will automatically\n"
" voice people with the <channel>,voice capability when they join the\n"
" channel."
msgstr ""
"Määrittää antaako botti automaattisesti äänen ihmisille, joilla on #<kanava>,"
"voice\n"
" valtuus heidän liittyessään kanavalle."
#: config.py:73
msgid ""
"Determines whether the bot will automatically\n"
" ban people who join the channel and are on the banlist."
msgstr ""
"Määrittää antaako botti porttikiellon ihmisille,\n"
" jotka liittyvät kanavalle ja ovat porttikieltolistalla."
#: config.py:76
msgid ""
"Determines how many seconds the bot\n"
" will automatically ban a person when banning."
msgstr ""
"Määrittää kuinka moneksi sekuntiksi botti antaa porttikiellon henkilöle, "
"antaessaan\n"
" porttikieltoa automaattisesti."
#: config.py:80
msgid ""
"Determines how many seconds the bot will wait\n"
" before applying a mode. Has no effect on bans."
msgstr ""
"Määrittää kuinka monta sekuntia botti odottaa ennen, kuin asettaa tilan. "
"Tällä ei ole\n"
" vaikutusta porttikieltoihin."
#: config.py:84
msgid ""
"Extra modes that will be\n"
" applied to a user. Example syntax: user1+o-v user2+v user3-v"
msgstr ""
"Ylimääräiset tilat, jotka asetetaan käyttäjään.\n"
" Esimerkki syntaksi: käyttäjä1+o-v käyttäjä2+v käyttäjä3-v"
#: plugin.py:49
msgid ""
"\n"
" This plugin, when configured, allows the bot to automatically set modes\n"
" on users when they join.\n"
"\n"
" * if ``plugins.automode.op`` is set to ``True``, users with the\n"
" ``#channel,op`` capability are opped when they join.\n"
" * if ``plugins.automode.halfop`` is set to ``True``, users with the\n"
" ``#channel,halfop`` are halfopped when they join.\n"
" * if ``plugins.automode.voice`` is set to ``True``, users with the\n"
" ``#channel,voice`` are voiced when they join.\n"
"\n"
" This plugin also kbans people on ``@channel ban list``\n"
" (``config plugins.automode.ban``) when they join and if moding users "
"with\n"
" lower capability is enabled, that is also applied to users with higher\n"
" capability (``config plugins.automode.fallthrough``).\n"
"\n"
" "
msgstr ""
#: plugin.py:97
msgid ""
"Determines whether or not a mode has already\n"
" been applied."
msgstr "Määrittää asettaako botti tilan vai eikö, jos tila se on jo asetettu."
#, fuzzy
#~ msgid ""
#~ "This plugin, when configured, allows the bot to automatically set modes\n"
#~ " on users when they join."
#~ msgstr ""
#~ "Määritettynä tämä plugin voi asettaa tiloja kanavalle liittyjiin "
#~ "automaattisesti."

View File

@ -1,134 +0,0 @@
# Valentin Lorentz <progval@progval.net>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2014-01-21 19:33+0100\n"
"Last-Translator: \n"
"Language-Team: French <kde-i18n-doc@kde.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: ASCII\n"
"X-Generator: Poedit 1.5.4\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: config.py:47
msgid ""
"Determines whether this plugin is enabled.\n"
" "
msgstr "Détermine si ce plugin est activé."
#: config.py:50
msgid ""
"Determines whether this plugin will automode\n"
" owners even if they don't have op/halfop/voice/whatever capability."
msgstr ""
"Détermine si ce plugin mettra des modes automatiques sur les owners, même si "
"ils n'ont pas la capacité op/halfop/voice/..."
#: config.py:53
msgid ""
"Determines whether the bot will\n"
" check for 'alternative capabilities' (ie. autoop, autohalfop,\n"
" autovoice) in addition to/instead of classic ones."
msgstr ""
"Détermine si le bot vérifiera les « capacités alternatives » (ie. autoop, "
"autohalfop, autovoice) en plus/à la place des capacités classiques."
#: config.py:57
msgid ""
"Determines whether the bot will \"fall\n"
" through\" to halfop/voicing when auto-opping is turned off but\n"
" auto-halfopping/voicing are turned on."
msgstr ""
"Détermine si le bot ne halfopera/voicera pas lorsque l'auto-op est "
"désactivé, même si l'auto-halfopvoice est activé."
#: config.py:61
msgid ""
"Determines whether the bot will automatically\n"
" op people with the <channel>,op capability when they join the channel.\n"
" "
msgstr ""
"Détermine si le bot opera automatiquement les gens qui ont la capacité "
"<canal>,op lorsqu'ils rejoignent le canal."
#: config.py:65
msgid ""
"Determines whether the bot will automatically\n"
" halfop people with the <channel>,halfop capability when they join the\n"
" channel."
msgstr ""
"Détermine si le bot halfopera les gens qui ont la capacité <canal>,halfop "
"lorsqu'ils rejoignent le canal."
#: config.py:69
msgid ""
"Determines whether the bot will automatically\n"
" voice people with the <channel>,voice capability when they join the\n"
" channel."
msgstr ""
"Détermine si le bot voicera automatiquement les gens avec la capacité "
"<canal>,voice lorsqu'ils rejoingent le canal."
#: config.py:73
msgid ""
"Determines whether the bot will automatically\n"
" ban people who join the channel and are on the banlist."
msgstr ""
"Détermine si le bot bannira automatiquement les personnes qui rejoignent le "
"canal et qui sont sur la liste de bannissement."
#: config.py:76
msgid ""
"Determines how many seconds the bot\n"
" will automatically ban a person when banning."
msgstr ""
"Détermine combien de secondes durera le bannissement que le bot posera sur "
"une personne."
#: config.py:80
msgid ""
"Determines how many seconds the bot will wait\n"
" before applying a mode. Has no effect on bans."
msgstr ""
"Détermine combien de secondes le bot attendra avant d'appliquer un mode. "
"Cela n'a aucun effet sur les bannissements."
#: config.py:84
msgid ""
"Extra modes that will be\n"
" applied to a user. Example syntax: user1+o-v user2+v user3-v"
msgstr ""
"Des modes supplémentaires à appliquer à un utilisateur. Par exemple : "
"user1+o-v user2+v user3-v"
#: plugin.py:49
msgid ""
"\n"
" This plugin, when configured, allows the bot to automatically set modes\n"
" on users when they join.\n"
"\n"
" * if ``plugins.automode.op`` is set to ``True``, users with the\n"
" ``#channel,op`` capability are opped when they join.\n"
" * if ``plugins.automode.halfop`` is set to ``True``, users with the\n"
" ``#channel,halfop`` are halfopped when they join.\n"
" * if ``plugins.automode.voice`` is set to ``True``, users with the\n"
" ``#channel,voice`` are voiced when they join.\n"
"\n"
" This plugin also kbans people on ``@channel ban list``\n"
" (``config plugins.automode.ban``) when they join and if moding users "
"with\n"
" lower capability is enabled, that is also applied to users with higher\n"
" capability (``config plugins.automode.fallthrough``).\n"
"\n"
" "
msgstr ""
#: plugin.py:97
msgid ""
"Determines whether or not a mode has already\n"
" been applied."
msgstr "Détermine si un mode a déjà été appliqué ou non."

View File

@ -1,131 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: Limnoria\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\n"
"PO-Revision-Date: 2012-04-23 19:29+0200\n"
"Last-Translator: skizzhg <skizzhg@gmx.com>\n"
"Language-Team: Italian <skizzhg@gmx.com>\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: config.py:47
msgid ""
"Determines whether this plugin is enabled.\n"
" "
msgstr ""
"Determina se il plugin è abilitato.\n"
" "
#: config.py:50
msgid ""
"Determines whether this plugin will automode\n"
" owners even if they don't have op/halfop/voice/whatever capability."
msgstr ""
"Determina se il plugin darà automaticamente il mode ai proprietari.\n"
" anche se non hanno la capacità op, halfop, voice, ecc..."
#: config.py:53
msgid ""
"Determines whether the bot will\n"
" check for 'alternative capabilities' (ie. autoop, autohalfop,\n"
" autovoice) in addition to/instead of classic ones."
msgstr ""
#: config.py:57
msgid ""
"Determines whether the bot will \"fall\n"
" through\" to halfop/voicing when auto-opping is turned off but\n"
" auto-halfopping/voicing are turned on."
msgstr ""
"Determina se il the bot non darà l'halfop o il voice\n"
" quando l'op automatico è disabilitato ma l'halfop o il voice\n"
" automatico sono attivati."
#: config.py:61
msgid ""
"Determines whether the bot will automatically\n"
" op people with the <channel>,op capability when they join the channel.\n"
" "
msgstr ""
"Determina se il bot darà automaticamente l'op agli utenti che hanno\n"
" la capacità <canale>,op quando entrano in canale.\n"
" "
#: config.py:65
msgid ""
"Determines whether the bot will automatically\n"
" halfop people with the <channel>,halfop capability when they join the\n"
" channel."
msgstr ""
"Determina se il bot darà automaticamente l'halfop agli utenti che hanno\n"
" la capacità <canale>,halfop quando entrano in canale.\n"
" "
#: config.py:69
msgid ""
"Determines whether the bot will automatically\n"
" voice people with the <channel>,voice capability when they join the\n"
" channel."
msgstr ""
"Determina se il bot darà automaticamente il voice agli utenti che hanno\n"
" la capacità <canale>,voice quando entrano in canale.\n"
" "
#: config.py:73
msgid ""
"Determines whether the bot will automatically\n"
" ban people who join the channel and are on the banlist."
msgstr ""
"Determina se il bot bannerà automaticamente gli utenti che\n"
" entrano in canale e sono nella lista dei ban.\n"
" "
#: config.py:76
msgid ""
"Determines how many seconds the bot\n"
" will automatically ban a person when banning."
msgstr "Determina quanti secondi durerà il ban applicato a un utente."
#: config.py:80
msgid ""
"Determines how many seconds the bot will wait\n"
" before applying a mode. Has no effect on bans."
msgstr ""
"Determina quanti secondi aspetterà il bot prima di applicare un mode.\n"
" Non ha effetto sui ban."
#: config.py:84
msgid ""
"Extra modes that will be\n"
" applied to a user. Example syntax: user1+o-v user2+v user3-v"
msgstr ""
#: plugin.py:49
msgid ""
"\n"
" This plugin, when configured, allows the bot to automatically set modes\n"
" on users when they join.\n"
"\n"
" * if ``plugins.automode.op`` is set to ``True``, users with the\n"
" ``#channel,op`` capability are opped when they join.\n"
" * if ``plugins.automode.halfop`` is set to ``True``, users with the\n"
" ``#channel,halfop`` are halfopped when they join.\n"
" * if ``plugins.automode.voice`` is set to ``True``, users with the\n"
" ``#channel,voice`` are voiced when they join.\n"
"\n"
" This plugin also kbans people on ``@channel ban list``\n"
" (``config plugins.automode.ban``) when they join and if moding users "
"with\n"
" lower capability is enabled, that is also applied to users with higher\n"
" capability (``config plugins.automode.fallthrough``).\n"
"\n"
" "
msgstr ""
#: plugin.py:97
msgid ""
"Determines whether or not a mode has already\n"
" been applied."
msgstr ""

View File

@ -1,117 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2022-02-06 00:12+0100\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: config.py:47
msgid ""
"Determines whether this plugin is enabled.\n"
" "
msgstr ""
#: config.py:50
msgid ""
"Determines whether this plugin will automode\n"
" owners even if they don't have op/halfop/voice/whatever capability."
msgstr ""
#: config.py:53
msgid ""
"Determines whether the bot will\n"
" check for 'alternative capabilities' (ie. autoop, autohalfop,\n"
" autovoice) in addition to/instead of classic ones."
msgstr ""
#: config.py:57
msgid ""
"Determines whether the bot will \"fall\n"
" through\" to halfop/voicing when auto-opping is turned off but\n"
" auto-halfopping/voicing are turned on."
msgstr ""
#: config.py:61
msgid ""
"Determines whether the bot will automatically\n"
" op people with the <channel>,op capability when they join the channel.\n"
" "
msgstr ""
#: config.py:65
msgid ""
"Determines whether the bot will automatically\n"
" halfop people with the <channel>,halfop capability when they join the\n"
" channel."
msgstr ""
#: config.py:69
msgid ""
"Determines whether the bot will automatically\n"
" voice people with the <channel>,voice capability when they join the\n"
" channel."
msgstr ""
#: config.py:73
msgid ""
"Determines whether the bot will automatically\n"
" ban people who join the channel and are on the banlist."
msgstr ""
#: config.py:76
msgid ""
"Determines how many seconds the bot\n"
" will automatically ban a person when banning."
msgstr ""
#: config.py:80
msgid ""
"Determines how many seconds the bot will wait\n"
" before applying a mode. Has no effect on bans."
msgstr ""
#: config.py:84
msgid ""
"Extra modes that will be\n"
" applied to a user. Example syntax: user1+o-v user2+v user3-v"
msgstr ""
#: plugin.py:49
#, docstring
msgid ""
"\n"
" This plugin, when configured, allows the bot to automatically set modes\n"
" on users when they join.\n"
"\n"
" * if ``plugins.automode.op`` is set to ``True``, users with the\n"
" ``#channel,op`` capability are opped when they join.\n"
" * if ``plugins.automode.halfop`` is set to ``True``, users with the\n"
" ``#channel,halfop`` are halfopped when they join.\n"
" * if ``plugins.automode.voice`` is set to ``True``, users with the\n"
" ``#channel,voice`` are voiced when they join.\n"
"\n"
" This plugin also kbans people on ``@channel ban list``\n"
" (``config plugins.automode.ban``) when they join and if moding users with\n"
" lower capability is enabled, that is also applied to users with higher\n"
" capability (``config plugins.automode.fallthrough``).\n"
"\n"
" "
msgstr ""
#: plugin.py:97
#, docstring
msgid ""
"Determines whether or not a mode has already\n"
" been applied."
msgstr ""

View File

@ -1,179 +0,0 @@
###
# Copyright (c) 2004, Jeremiah Fincher
# Copyright (c) 2009, James McCoy
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
import re
import time
import supybot.log as log
import supybot.conf as conf
import supybot.ircdb as ircdb
import supybot.ircmsgs as ircmsgs
import supybot.ircutils as ircutils
import supybot.schedule as schedule
import supybot.callbacks as callbacks
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('AutoMode')
class Continue(Exception):
pass # Used below, look in the "do" function nested in doJoin.
class AutoMode(callbacks.Plugin):
"""
This plugin, when configured, allows the bot to automatically set modes
on users when they join.
* if ``plugins.automode.op`` is set to ``True``, users with the
``#channel,op`` capability are opped when they join.
* if ``plugins.automode.halfop`` is set to ``True``, users with the
``#channel,halfop`` are halfopped when they join.
* if ``plugins.automode.voice`` is set to ``True``, users with the
``#channel,voice`` are voiced when they join.
This plugin also kbans people on ``@channel ban list``
(``config plugins.automode.ban``) when they join and if moding users with
lower capability is enabled, that is also applied to users with higher
capability (``config plugins.automode.fallthrough``).
"""
def doJoin(self, irc, msg):
channel = msg.channel
network = irc.network
if ircutils.strEqual(irc.nick, msg.nick):
return
if not self.registryValue('enable', channel, network):
return
fallthrough = self.registryValue('fallthrough', channel, network)
def do(type):
cap = ircdb.makeChannelCapability(channel, type)
cap_auto = ircdb.makeChannelCapability(channel, 'auto'+type)
try:
apply_mode = ircdb.checkCapability(msg.prefix, cap,
ignoreOwner=not self.registryValue('owner'),
ignoreChannelOp=True, ignoreDefaultAllow=True)
except KeyError:
apply_mode = False
if self.registryValue('alternativeCapabilities', channel, network):
try:
override = ircdb.checkCapability(msg.prefix, cap_auto,
ignoreOwner=not self.registryValue('owner'),
ignoreChannelOp=True, ignoreDefaultAllow=True)
except KeyError:
override = False
else:
override = False
if apply_mode or override:
if override or self.registryValue(type, channel, network):
self.log.info('Scheduling auto-%s of %s in %s @ %s.',
type, msg.prefix, channel, network)
def dismiss():
"""Determines whether or not a mode has already
been applied."""
l = getattr(irc.state.channels[channel], type+'s')
return (msg.nick in l)
msgmaker = getattr(ircmsgs, type)
schedule_msg(msgmaker(channel, msg.nick),
dismiss)
raise Continue # Even if fallthrough, let's only do one.
elif not fallthrough:
self.log.debug('%s has %s, but supybot.plugins.AutoMode.%s'
' is not enabled in %s @ %s, refusing to '
'fall through.',
msg.prefix, cap, type, channel, network)
raise Continue
def schedule_msg(msg, dismiss):
def f():
if not dismiss():
irc.queueMsg(msg)
else:
self.log.info('Dismissing auto-mode for %s.', msg.args[2])
delay = self.registryValue('delay', channel, network)
if delay:
schedule.addEvent(f, time.time() + delay)
else:
f()
def extra_modes():
try:
user = ircdb.users.getUser(ircdb.users.getUserId(msg.prefix))
except KeyError:
return
pattern = re.compile(r'-|\+')
for item in self.registryValue('extra', channel, network):
try:
username, modes = pattern.split(item, maxsplit=1)
modes = item[len(username)] + modes
except ValueError: # No - or + in item
log.error(('%r is not a valid item for '
'supybot.plugins.AutoMode.extra') % item)
continue
if username != user.name:
continue
else:
self.log.info('Scheduling auto-modes %s of %s in %s @ %s.',
modes, msg.prefix, channel, network)
modes = [modes] + \
([msg.nick]*len(pattern.sub('', modes)))
schedule_msg(ircmsgs.mode(channel, modes), lambda :False)
break
try:
do('op')
if 'h' in irc.state.supported.get('prefix', ''):
do('halfop')
except Continue:
return
finally:
extra_modes()
c = ircdb.channels.getChannel(channel)
if c.checkBan(msg.prefix) and self.registryValue('ban',
channel, network):
period = self.registryValue('ban.period', channel, network)
if period:
def unban():
try:
if msg.prefix in irc.state.channels[channel].bans:
irc.queueMsg(ircmsgs.unban(channel, msg.prefix))
except KeyError:
# We're not in the channel anymore.
pass
schedule.addEvent(unban, time.time()+period)
banmask =conf.supybot.protocols.irc.banmask.makeBanmask(msg.prefix)
irc.queueMsg(ircmsgs.ban(channel, banmask))
irc.queueMsg(ircmsgs.kick(channel, msg.nick))
try:
do('voice')
except Continue:
return
Class = AutoMode
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,37 +0,0 @@
###
# Copyright (c) 2005, Jeremiah Fincher
# Copyright (c) 2010-2021, Valentin Lorentz
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions, and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions, and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the author of this software nor the name of
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written consent.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
from supybot.test import *
class AutoModeTestCase(PluginTestCase):
plugins = ('AutoMode',)
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -1,44 +0,0 @@
.. _plugin-Autocomplete:
Documentation for the Autocomplete plugin for Supybot
=====================================================
Purpose
-------
Autocomplete: Provides command autocompletion for IRC clients that support it.
This plugin implements an early draft of the IRCv3 autocompletion client tags.
As this is not yet a released specification, it does nothing unless
``supybot.protocols.irc.experimentalExtensions`` is set to True (keep it set to
False unless you know what you are doing).
If you are interested in this feature, please contribute to
`the discussion <https://github.com/ircv3/ircv3-specifications/pull/415>`_
Usage
-----
Provides command completion for IRC clients that support it.
.. _conf-Autocomplete:
Configuration
-------------
.. _conf-supybot.plugins.Autocomplete.enabled:
supybot.plugins.Autocomplete.enabled
This config variable defaults to "False", is network-specific, and is channel-specific.
Whether the bot should reply to autocomplete requests from clients.
.. _conf-supybot.plugins.Autocomplete.public:
supybot.plugins.Autocomplete.public
This config variable defaults to "True", is not network-specific, and is not channel-specific.
Determines whether this plugin is publicly visible.

Some files were not shown because too many files have changed in this diff Show More