Compare commits

..

1 commit

Author SHA1 Message Date
BFlow 4667c260cd Add new directory 2019-10-02 17:50:08 +00:00
31 changed files with 482 additions and 2076 deletions

2
.gitignore vendored
View file

@ -76,7 +76,7 @@ docs/make.bat
dev.cfg dev.cfg
prod.cfg prod.cfg
exploit_overrides.cfg exploit_overrides.cfg
#buildout.cfg buildout.cfg
config.ini config.ini
mr-dev/* mr-dev/*
.mr.developer.cfg .mr.developer.cfg

View file

@ -1,29 +0,0 @@
stages:
- login
- build
- push
- deploy
variables:
GL_TOKEN: $GL_TOKEN
VERSION: '0.2.18'
deploy:
stage: deploy
script : sudo docker-compose --env-file /data/docker/compose-files/others.env -f /data/docker/compose-files/others.yml up -d
build:
stage: build
script:
- sudo docker build -t hub.0w.tf/milka64/kabot:$VERSION .
- sudo docker build -t hub.0w.tf/milka64/kabot:latest .
push:
stage: push
script:
- sudo docker push hub.0w.tf/milka64/kabot:$VERSION
- sudo docker push hub.0w.tf/milka64/kabot:latest
login:
stage: login
script: sudo docker login -u milka64 -p $GL_TOKEN hub.0w.tf

BIN
Benjamin_Prejent.mp3 Normal file

Binary file not shown.

View file

@ -1,12 +0,0 @@
FROM python:3.11
WORKDIR /usr/src/kabot
ENV CONFIG_FILE=/data/config.ini
COPY kabot ./
COPY config.ini.sample /data/config.ini
COPY entrypoint.sh /
RUN apt update && apt install -y ffmpeg
RUN apt clean
RUN pip install --no-cache-dir /usr/src/kabot/
CMD [ "/entrypoint.sh" ]

View file

@ -10,7 +10,7 @@ Prerquire :
pip3 install zc.buildout pip3 install zc.buildout
clone this repository, then : clone this repositori, then :
.. code-block:: bash .. code-block:: bash
@ -22,34 +22,4 @@ Utilisation
.. code-block:: bash .. code-block:: bash
./bin/kabot -c config.ini ./bin/kabot
Configuration
-------------
.. code-block:: ini
[DEFAULT]
audio_path = /tmp/
voice_channel = channel_name
text_channel = channel_name
[discord]
token = <discord_token>
[gitlab]
url = https://gitlab.example.com/
token = <GITLAB_TOKEN>
[giphy]
token = <GIPHY_TOKEN>
Docker
------
.. code-block:: bash
docker build -t kabot .
docker run -v /pa/to/your/data:/data kabot:latest

210
bootstrap-buildout.py Normal file
View file

@ -0,0 +1,210 @@
##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os
import shutil
import sys
import tempfile
from optparse import OptionParser
__version__ = '2015-07-01'
# See zc.buildout's changelog if this version is up to date.
tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --find-links to point to local resources, you can keep
this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("--version",
action="store_true", default=False,
help=("Return bootstrap.py version."))
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
help=("Normally, if you do not specify a --version, the "
"bootstrap script and buildout gets the newest "
"*final* versions of zc.buildout and its recipes and "
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
parser.add_option("-f", "--find-links",
help=("Specify a URL to search for buildout releases"))
parser.add_option("--allow-site-packages",
action="store_true", default=False,
help=("Let bootstrap.py use existing site packages"))
parser.add_option("--buildout-version",
help="Use a specific zc.buildout version")
parser.add_option("--setuptools-version",
help="Use a specific setuptools version")
parser.add_option("--setuptools-to-dir",
help=("Allow for re-use of existing directory of "
"setuptools versions"))
options, args = parser.parse_args()
if options.version:
print("bootstrap.py version %s" % __version__)
sys.exit(0)
######################################################################
# load/install setuptools
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ez = {}
if os.path.exists('ez_setup.py'):
exec(open('ez_setup.py').read(), ez)
else:
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
if not options.allow_site_packages:
# ez_setup imports site, which adds site packages
# this will remove them from the path to ensure that incompatible versions
# of setuptools are not in the path
import site
# inside a virtualenv, there is no 'getsitepackages'.
# We can't remove these reliably
if hasattr(site, 'getsitepackages'):
for sitepackage_path in site.getsitepackages():
# Strip all site-packages directories from sys.path that
# are not sys.prefix; this is because on Windows
# sys.prefix is a site-package directory.
if sitepackage_path != sys.prefix:
sys.path[:] = [x for x in sys.path
if sitepackage_path not in x]
setup_args = dict(to_dir=tmpeggs, download_delay=0)
if options.setuptools_version is not None:
setup_args['version'] = options.setuptools_version
if options.setuptools_to_dir is not None:
setup_args['to_dir'] = options.setuptools_to_dir
ez['use_setuptools'](**setup_args)
import setuptools
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
######################################################################
# Install buildout
ws = pkg_resources.working_set
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
# Fix sys.path here as easy_install.pth added before PYTHONPATH
cmd = [sys.executable, '-c',
'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs]
find_links = os.environ.get(
'bootstrap-testing-find-links',
options.find_links or
('http://downloads.buildout.org/'
if options.accept_buildout_test_releases else None)
)
if find_links:
cmd.extend(['-f', find_links])
requirement = 'zc.buildout'
version = options.buildout_version
if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
try:
return not parsed_version.is_prerelease
except AttributeError:
# Older setuptools
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setuptools_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
if index.obtain(req) is not None:
best = []
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
bestv = distv
elif distv == bestv:
best.append(dist)
if best:
best.sort()
version = best[-1].version
if version:
requirement = '=='.join((requirement, version))
cmd.append(requirement)
import subprocess
if subprocess.call(cmd) != 0:
raise Exception(
"Failed to execute command:\n%s" % repr(cmd)[1:-1])
######################################################################
# Import and run buildout
ws.add_entry(tmpeggs)
ws.require(requirement)
import zc.buildout.buildout
if not [a for a in args if '=' not in a]:
args.append('bootstrap')
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args[0:0] = ['-c', options.config_file]
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)

View file

@ -1,16 +0,0 @@
[DEFAULT]
logs = /var/log/kabot.log
audio_path = /tmp/
voice_channel = channel_name
text_channel = channel_name
[discord]
token = <discord_token>
[gitlab]
url = https://gitlab.example.com/
token = <GITLAB_TOKEN>
[giphy]
token = <GIPHY_TOKEN>

View file

@ -1,3 +0,0 @@
#!/bin/sh
kabot -c $CONFIG_FILE

15
kabot/.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,15 @@
* Kabot version:
* Python version:
* Operating System:
### Description
Describe what you were trying to get done.
Tell us what happened, what went wrong, and what you expected to happen.
### What I Did
```
Paste the command(s) you ran and the output.
If there was a crash, please include the traceback here.
```

View file

@ -3,7 +3,6 @@ include CONTRIBUTING.rst
include HISTORY.rst include HISTORY.rst
include LICENSE include LICENSE
include README.rst include README.rst
include kabot/utils/ressources/*
recursive-include tests * recursive-include tests *
recursive-exclude * __pycache__ recursive-exclude * __pycache__

88
kabot/Makefile Normal file
View file

@ -0,0 +1,88 @@
.PHONY: clean clean-test clean-pyc clean-build docs help
.DEFAULT_GOAL := help
define BROWSER_PYSCRIPT
import os, webbrowser, sys
try:
from urllib import pathname2url
except:
from urllib.request import pathname2url
webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
endef
export BROWSER_PYSCRIPT
define PRINT_HELP_PYSCRIPT
import re, sys
for line in sys.stdin:
match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
if match:
target, help = match.groups()
print("%-20s %s" % (target, help))
endef
export PRINT_HELP_PYSCRIPT
BROWSER := python -c "$$BROWSER_PYSCRIPT"
help:
@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
clean-build: ## remove build artifacts
rm -fr build/
rm -fr dist/
rm -fr .eggs/
find . -name '*.egg-info' -exec rm -fr {} +
find . -name '*.egg' -exec rm -f {} +
clean-pyc: ## remove Python file artifacts
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} +
find . -name '__pycache__' -exec rm -fr {} +
clean-test: ## remove test and coverage artifacts
rm -fr .tox/
rm -f .coverage
rm -fr htmlcov/
rm -fr .pytest_cache
lint: ## check style with flake8
flake8 kabot tests
test: ## run tests quickly with the default Python
python setup.py test
test-all: ## run tests on every Python version with tox
tox
coverage: ## check code coverage quickly with the default Python
coverage run --source kabot setup.py test
coverage report -m
coverage html
$(BROWSER) htmlcov/index.html
docs: ## generate Sphinx HTML documentation, including API docs
rm -f docs/kabot.rst
rm -f docs/modules.rst
sphinx-apidoc -o docs/ kabot
$(MAKE) -C docs clean
$(MAKE) -C docs html
$(BROWSER) docs/_build/html/index.html
servedocs: docs ## compile the docs watching for changes
watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D .
release: dist ## package and upload a release
twine upload dist/*
dist: clean ## builds source and wheel package
python setup.py sdist
python setup.py bdist_wheel
ls -l dist
install: clean ## install the package to the active Python's site-packages
python setup.py install

View file

@ -1,8 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """Top-level package for Kabot."""
Top-level package for Kabot.
"""
__author__ = """Michaël Ricart""" __author__ = """Michaël Ricart"""
__email__ = 'michael.ricart@0w.tf' __email__ = 'michael.ricart@0w.tf'

View file

@ -1,101 +1,106 @@
# This example requires the 'message_content' privileged intent to function. # -*- coding: utf-8 -*-
import asyncio """Main module."""
import random
import discord import discord
import yt_dlp as youtube_dl
from discord.ext import commands from discord.ext import commands
from kabot.utils.audio import *
from kabot.utils.texte import *
import os
import requests
class Mybot(commands.Cog):
def __init__(self, bot):
self.bot = bot
intents = discord.Intents.all() @commands.command()
intents.message_content = True async def join(self, ctx):
channel = [x for x in self.bot.get_all_channels() if x.name == "Général"][0]
await channel.connect()
bot = commands.Bot( @commands.command()
command_prefix="!", async def disconnect(self, ctx):
description='''A ROULEEEEETTES !! await ctx.guild.voice_client.disconnect()
HOULA... J'l'ai un peu trop gueulé ça, non ?
A roulettes.''',
intents=intents,
)
@commands.command()
async def benjamin(self, ctx):
source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio("/tmp/Benjamin_Prejent.mp3"))
ctx.voice_client.play(source, after=lambda e: print('Player error: %s' % e) if e else None)
await ctx.send('Now playing')
@bot.event @commands.command(help='check if bot always online')
async def on_ready(): async def ping(self, message):
print(f'Logged in as {bot.user} (ID: {bot.user.id})') await message.channel.send('pong')
print('------')
@commands.command(help="optionnal args : [livre] [character]")
async def main(): async def kaamelott(self, ctx, *args):
## création de l'objet logger response = None
logger = logging.getLogger() if not args:
## definition du log level url = 'https://kaamelott.chaudie.re/api/random'
logger.setLevel(logging.INFO)
parser = argparse.ArgumentParser()
parser.add_argument(
"-c",
"--config",
help="config file",
default="config.ini"
)
args = parser.parse_args()
config = configparser.ConfigParser()
if not os.path.exists(args.config):
logger.critical('config file not found')
exit(1)
config.read(args.config)
log_file = config['DEFAULT']['logs']
## definition du fichier de log (chemin, level, etc ...)
formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(message)s')
file_handler = RotatingFileHandler(log_file, 'a', 1000000, 1)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
if "nickname" in config['DEFAULT']:
nickname = config['DEFAULT']['nickname']
else: else:
nickname = None args = list(args)
if "voice_channel" in config['DEFAULT']: if args[0].isdigit():
voice_channel = config['DEFAULT']['voice_channel'] livre = int(args[0])
args.pop(0)
elif args[-1].isdigit():
livre = int(args[-1])
args.pop(-1)
else: else:
voice_channel = None livre = None
if "text_channel" in config['DEFAULT']: if args:
text_channel = config['DEFAULT']['text_channel'] perso = ' '.join(args)
if perso and livre:
url = 'https://kaamelott.chaudie.re/api/random/livre/%s/personnage/%s' % (livre,perso)
elif perso:
url = 'https://kaamelott.chaudie.re/api/random/personnage/%s' % perso
else: else:
text_channel = None url = 'https://kaamelott.chaudie.re/api/random/livre/%s' % livre
audio_path = config['DEFAULT']['audio_path'] try:
token = config['discord']['token'] citation = requests.get(url).json()['citation']
gl_url = config['gitlab']['url'] response = "%s :\n```\n%s\n```" % (citation['infos']['personnage'], citation['citation'])
gl_token = config['gitlab']['token'] except:
gif_token = config['giphy']['token'] response = "Unknow error, try: !kaamelott [livre] [character]"
async with bot: await ctx.send(response)
await bot.add_cog(
Audio(
bot, def main():
voice_chan=voice_channel, token = "NjI3MTM3NDY1MDA5ODMxOTQ2.XY4Raw.pw8sAen3bNR5aYsoTChQOudM0L8"
text_chan=text_channel, bot = commands.Bot(command_prefix='!')
audio_path=audio_path,
) @bot.event
) async def on_message(message):
await bot.add_cog( print(message.content)
Texte( if message.author == bot.user:
bot, return
gif_token=gif_token, else:
gl_token=gl_token, if bot.user in message.mentions \
gl_url=gl_url, and len(message.mentions) < 3 \
text_chan=text_channel, and len(message.content.splitlines()) == 1:
) path = '/tmp/%s.log' % message.channel
) with open(path, 'r') as f :
await bot.start(token) lines = f.read().splitlines()
if not message.content in lines:
with open(path, 'a') as f :
f.write(message.content + '\n')
response = random.choice(lines).replace(str(bot.user.id), str(message.author.id))
await message.channel.send(response)
await bot.process_commands(message)
@bot.event
async def on_voice_state_update(member,before,after):
if "BFlow" in member.name:
if before.channel is None and after.channel:
for channel in bot.get_all_channels():
if channel.name == "général":
current_chan = channel
ctx = bot.get_context(current_chan.last_message)
benjamin = bot.get_command('benjamin')
await benjamin.invoke(ctx)
bot.add_cog(Mybot(bot))
bot.run(token)
def run():
asyncio.run(main())
if __name__ == "__main__": if __name__ == "__main__":
run() main()

View file

@ -1 +0,0 @@
##

View file

@ -1,317 +0,0 @@
# This example requires the 'message_content' privileged intent to function.
import asyncio
import discord
import yt_dlp as youtube_dl
import random
import os
from discord.ext import commands, tasks
from pathlib import Path
# Suppress noise about console usage from errors
youtube_dl.utils.bug_reports_message = lambda: ''
ytdl_format_options = {
'format': 'bestaudio/mp3',
'outtmpl': '/tmp/discord_%(title)s-%(id)s.%(ext)s',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}]
}
ffmpeg_options = {
'options': '-vn',
}
ytdl = youtube_dl.YoutubeDL(ytdl_format_options)
class YTDLSource(discord.PCMVolumeTransformer):
def __init__(self, source, *, data, volume=0.5):
super().__init__(source, volume)
self.data = data
self.title = data.get('title')
self.url = data.get('url')
@classmethod
async def from_url(cls, url, *, loop=None, stream=False):
loop = loop or asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream))
if 'entries' in data:
# take first item from a playlist
data = data['entries'][0]
filename = data['url'] if stream else ytdl.prepare_filename(data)
extension = filename.split('.')[-1]
filename = filename.replace(extension, 'mp3')
return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data)
@classmethod
async def from_file(cls, audio_file, ctx, *, loop=None, stream=False):
source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(audio_file,**ffmpeg_options))
ctx.voice_client.play(source, after=lambda e: print('Player error: %s' % e) if e else None)
class Audio(commands.Cog, name="Commandes Audio"):
def __init__(
self,
bot,
audio_path=None,
voice_chan=None,
text_chan=None):
self.bot = bot
self.sounds = []
self.voice_chan = voice_chan
self.text_chan = text_chan
self.audio_path = audio_path
self.sounds_history = []
@commands.Cog.listener()
async def on_voice_state_update(self, member, before, after):
if before.channel is None and after.channel:
for channel in self.bot.get_all_channels():
if channel.name == self.text_chan:
current_chan = channel
async for msg in current_chan.history(limit=1):
last_message = msg
ctx = await self.bot.get_context(last_message)
ctx.message.author = member
#welcome = bot.get_command('welcome')
await asyncio.sleep(2)
await self.welcome(ctx, member.display_name)
@commands.Cog.listener()
async def on_ready(self):
self.play_next.start()
self.pipelette.start()
if self.voice_chan:
await self.join(self.voice_chan)
#await self.welcome(None, 'kabot')
@commands.command(help="Toi tu fermes ta gueule! Tu la fermes définitivement")
async def mute(self, ctx, member: discord.Member=None, mute_time = 10):
if member.voice.mute:
async with ctx.channel.typing():
await asyncio.sleep(1)
await ctx.channel.send("Tu ne vas pas m'avoir si facilement")
return
if not member:
async with ctx.channel.typing():
await asyncio.sleep(1)
await ctx.channel.send("Qui veux-tu mute?")
return
if mute_time > 60:
async with ctx.channel.typing():
await asyncio.sleep(1)
await ctx.channel.send("Doucement sur le temps!")
return
member = ctx.message.mentions[0]
await member.edit(mute=True)
async with ctx.channel.typing():
await asyncio.sleep(1)
await ctx.send("Tu sors %s!" % member.mention)
await asyncio.sleep(mute_time)
await member.edit(mute=False)
async with ctx.channel.typing():
await asyncio.sleep(1)
await ctx.channel.send("Tu peux reparler %s!" % member.mention)
@commands.command(help="Appuie sur la detente PUSSY!")
async def roulette(self, ctx):
mute_time = 60
member = ctx.message.author
if not member.voice:
async with ctx.typing():
await ctx.channel.send("You're not in voice channel")
return
barillet = [False, False, True, False, False]
bullet = random.choice(barillet)
await self.joke(ctx, "spinning_and_closed.mp3")
if bullet == True:
await self.joke(ctx, "omawa_shindeiru.mp3")
await asyncio.sleep(2)
await member.edit(mute=True)
async with ctx.typing():
await asyncio.sleep(3)
await ctx.channel.send("Perdu, tu es mute pendant 60 secondes!")
else:
await self.joke(ctx, "hammer_and_dry.mp3")
async with ctx.typing():
await asyncio.sleep(3)
await ctx.channel.send("Gagné, tu ne seras pas mute!")
return
await asyncio.sleep(mute_time)
await member.edit(mute=False)
async with ctx.typing():
await asyncio.sleep(0.5)
await ctx.channel.send("Tu peux reparler %s!" % member.mention)
@tasks.loop(seconds=300)
async def pipelette(self):
for channel in self.bot.get_all_channels():
if channel.name == self.voice_chan and\
len(channel.members) > 1 and\
random.choice([True,True,True]):
for chan in self.bot.get_all_channels():
if chan.name == self.text_chan:
current_chan = chan
await asyncio.sleep(random.choice(range(305)))
async for msg in current_chan.history(limit=1):
last_message = msg
ctx = await self.bot.get_context(last_message)
ctx.message.content = ""
await self.joke(ctx)
@tasks.loop(seconds=1)
async def play_next(self):
connected_voice = [chan for chan in self.bot.voice_clients if chan.is_connected()]
if connected_voice:
if not [chan for chan in connected_voice if chan.is_playing()]:
if self.sounds:
audio_type, audio_file, ctx = self.sounds[0]
if 'url' in audio_type:
player = await YTDLSource.from_url(audio_file, loop=self.bot.loop)
ctx.voice_client.play(player, after=lambda e: print(f'Player error: {e}') if e else None)
elif 'file' in audio_type:
player = await YTDLSource.from_file(audio_file, ctx)
last_audio = self.sounds.pop(0)
self.sounds_history.reverse()
self.sounds_history.append(last_audio)
self.sounds_history.reverse()
if len(self.sounds_history) > 5:
self.sounds_history = self.sounds_history[:5]
@commands.command(help='Troll commands', hidden=True)
async def okre(self, ctx):
await self.joke(ctx, "tu_dois_tout_donner.mp3")
@commands.command(help='Clear sound queue')
async def clear(self, ctx):
self.sounds = []
@commands.command()
async def welcome(self, ctx, user=None):
"""Joue le son d'accueil de l'utilisateur"""
if not user:
user = ctx.message.author.name
try:
audio_file = random.choice([f for f in os.listdir(self.audio_path + '%s/' % user) if f.endswith('.mp3')])
audio_file = self.audio_path + '/%s/' % user + audio_file
except:
audio_file = random.choice([f for f in Path(self.audio_path + '/').glob('**/*.mp3')])
self.sounds.append(('file', audio_file, ctx))
@commands.command()
async def repeat(self, ctx):
"""Rejouer le dernier son joué"""
user = ctx.message.author.name
source = self.sounds_history[0]
self.sounds.append(source)
@commands.command(help="detail du dernier son joué")
async def last(self, ctx, number = 1):
number = int(number)
for sound in self.sounds_history[0:number]:
await ctx.channel.send("```"+str(sound[1])+"```")
@commands.command()
async def join(self, chan_name: discord.VoiceChannel):
"""Joins a voice channel"""
#if ctx.voice_client is not None:
# return await ctx.voice_client.move_to(channel)
channel = [x for x in self.bot.get_all_channels() if x.name == chan_name][0]
return await channel.connect()
await channel.connect()
@commands.command()
async def play(self, ctx, *, url):
"""Plays from a url (almost anything youtube_dl supports)"""
self.sounds.append(('url',url,ctx))
@commands.command()
async def stream(self, ctx, *, url):
"""Streams from a url (same as yt, but doesn't predownload)"""
async with ctx.typing():
player = await YTDLSource.from_url(url, loop=self.bot.loop, stream=True)
ctx.voice_client.play(player, after=lambda e: print(f'Player error: {e}') if e else None)
await ctx.send(f'Now playing: {player.title}')
@commands.command()
async def stop(self, ctx):
"""Stoppe la lecture en cours"""
await ctx.voice_client.stop()
@commands.command()
async def volume(self, ctx, volume: int):
"""Changes the player's volume"""
if ctx.voice_client is None:
return await ctx.send("Not connected to a voice channel.")
ctx.voice_client.source.volume = volume / 100
await ctx.send(f"Changed volume to {volume}%")
@commands.command()
async def leave(self, ctx):
"""Stops and disconnects the bot from voice"""
await ctx.voice_client.disconnect()
@commands.command()
async def find(self, ctx, query):
"""Cherche un son dans la bibliothèque (5 resultat max)"""
query = query.lower()
audio_files = [f for f in Path(self.audio_path + '/').glob('**/*.mp3') if query in str(f).lower()]
if not audio_files:
await ctx.channel.send("%s not found" % query)
else:
for file in audio_files[:6]:
await ctx.channel.send("```"+str(file)+"```")
@commands.command()
async def joke(self, ctx, folder=None):
"""Joue un son (aléatoire par défaut)"""
try:
user = ctx.message.author.name
if not folder or not ctx.message.content:
audio_file = random.choice([f"{f}" for f in Path(self.audio_path + '/').glob('**/*.mp3')])
elif folder:
folder = folder.lower()
audio_files = [f for f in Path(self.audio_path + '/').glob('**/*.mp3') if folder in str(f).lower()]
if not audio_files:
await ctx.channel.send("%s not found" % folder)
return
else:
audio_file = random.choice(audio_files)
self.sounds.append(('file', audio_file, ctx))
except:
e = exc_info()[0]
await ctx.channel.send("Exception when calling joke: %s\n" % e)
@play.before_invoke
@joke.before_invoke
@repeat.before_invoke
@stream.before_invoke
async def ensure_voice(self, ctx):
if ctx.voice_client is None:
if ctx.author.voice:
await ctx.author.voice.channel.connect()
else:
await ctx.send("You are not connected to a voice channel.")
raise commands.CommandError("Author not connected to a voice channel.")
elif ctx.voice_client.is_playing():
pass

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

File diff suppressed because it is too large Load diff

View file

@ -1,100 +0,0 @@
Il faudrait une bonne purge à cette vaisselle!;Il faudrait une bonne verge à cette pucelle!
Ma belle-mère admire les rossignols du caroubier. ;Ma belle-mère admire les roubignolles du carossier.
Votre père a l'air mutin. ;Votre mère a l'air putain.
L'Empereur est arrivé à pied par la Chine.;L'Empereur est arrivé à chier par la pinne.
Est-ce un feu de poutre? ;Est-ce un peu de foutre?
Mammouth écrase les prix. ;Mammie écrase les prouts.
C'est ici qu'on pendit le fuselage de l'aviatrice.;C'est ici qu'on fendit le pucelage de l'aviatrice.
Les étudiantes admiraient le factum du recteur. ;Les étudiantes admiraient le rectum du facteur.
Les laborieuses populations du Cap.;Les laborieuses copulations du Pape.
La cuvette est pleine de bouillon. ;La buvette est pleine de couillons.
Le scorpion est malade. ;Le morpion escalade.
Quel beau métier: professeur! ;Quel beau fessier: prometteur!
Elle est folle de la messe.;Elle est molle de la fesse.
Dès qu'on touche à son petit banc, cet enfant boude. ;Des qu'on touche à son petit bout, cet enfant bande.
A la vue des Nippons, la Chine se soulève.;A la vue des nichons, la pine se soulève.
Glisser dans la piscine. ;Pisser dans la glicine.
Taisez-vous en bas! ;Baisez-vous en tas!
Ma soeur taille des jupes au Pirée.;Ma soeur taille des pipes aux jurés.
Pour bien dîner, il faut être peu. ;Pour bien pinner, il faut être deux.
Auberge de Vendée.;Aux verges de bander.
Chère collaboratrice, je vous laisse le choix dans la date.;Chère collaboratrice, je vous laisse le doigt dans la chatte.
Parachute.;Char à putes.
Couper les nouilles au sécateur.;Couper les couilles au sénateur.
Empiler les culottes.;Enculer les pilotes.
L'assistante brouille l'écoute de l'ingénieur qui a une panne de micro. ;L'assistante broute les couilles de l'ingénieur qui a une pine de maquereau.
Un mine de chapeau.;Une pine de chameau.
Arriver à Béziers la veille. ;Arriver à baiser la vieille.
J'ai des rebords à mes épaulettes. ;J'ai des remords à baiser Paulette.
Allons, chérie, essuie ça vite et bien.;Allons, chérie, essuie sa bite et vient.
Ces colonnes de gauchistes se branchent devant l'Irak. ;Ces cochonnes de Gaullistes se branlent devant Chirac.
La princesse aime la dotation du roi. ;La princesse aime la rotation du doigt.
La femme du capitaine à fait mander le marin à bord.;La femme du capitaine à fait bander le marin à mort.
À l'Éducation Nationale, on aime bien l'équipe en place. ;A l'Education Nationale, on aime bien les pipes en classe.
Escalope sur une salade.;Escalade sur une salope.
Le gros entrepreneur pétrit le béton à la tonne. ;Le gros entrepreneur pétrit le têton à la bonne.
La jeune paysanne rêve devant un beau vendeur. ;La jeune paysanne rêve devant un veau bandeur.
L'archéologue met dans des caisses le produit de ses fouilles. ;L'archéologue met dans des fesses le produit de ses couilles.
Cette femme habite les gîtes.;Cette femme agite les bites.
Le préfet de Nîmes voudrait plus d'écus pour son Gard. ;Le préfet de Nîmes voudrait plus d'égard pour son cul.
Souhaitez-vous, Monsieur, des nouilles encore?;Souhaitez-vous, Monsieur, des couilles en or?
Aucun homme n'est jamais assez fort pour ce calcul.;Aucun homme n'éjacule assez fort pour se calmer.
J'aime vachement votre frangin.;J'aime franchement votre vagin.
Je te verrais bien en curé, avec une calotte. ;Je te verrais bien enculé avec une carotte.
La philantropie de l'ouvrier charpentier.;La tripe en folie de l'ouvrier partant chier.
Deux carrioles sans mulet.;Deux marrioles s'enculaient.
La jeune fille revient de la ferme pleine d'espoir jusqu'au pont du Jura.;La jeune fille revient de la foire pleine de sperme jusqu'au ras du jupon.
Alors que les athées se battent, les abbés se taisent.;Alors que les abbés se tâtent, les athés se baisent.
Cette jolie fille habite Laval. ;Cette jolie fille avale la bite.
L'Afrique est bonne hôtesse quand la canicule nous emballe. ;La trique est bonne aux fesses quand le cannibale nous encule.
Ces soupers manquent de pains. ;Ces poupées manquent de seins.
Elle fait de délicieuses tripes aux papillotes. ;Elle fait de délicieuses pipes aux patriotes.
Madame, il faut secouer les mites de vos habits. ;Madame, il faut secouer les bites de vos amis.
Elle avait un chapelet de citrouilles autour du cou. ;Elle avait un chapelet de six couilles autour du trou.
Il courait tant de buts divers qu'il en perdait sa belle mine.;Il bourrait tant de culs divers qu'il emmerdait sa belle pine.
Devenu riche à force de peiner, l'ouvrier roule sur les pépettes.;SDevenu rêche à force de piner, l'ouvrier pèle sur les roupettes.
Un curé précis refuse toujours le tennis. ;Un cul rétrécis refuse toujours le pénis.
J'ai du tracas jusqu'au cou! ;J'ai du caca jusqu'au trou!
On ne peut pas dîner, si on est pas assez pur.;On ne peut pas piner, si on est pas assez dur.
Affaissant subitement son broc, le garçon laitier mouilla les fiches de la dactylo et chuta dans la jatte.;Abaissant subitement son froc, le garçon laitier fouilla les miches de la dactylo et juta dans la chatte.
Les nonnes aimeraient faire des chatouilles sur leur pape. ;Les nonnes aimeraient faire des papouilles sur leur chatte.
Cette jeune femme a l'art de décaler les sons. ;Cette jeune femme a l'art dessaler les cons.
La botaniste admire ce plan qui vient de la Guinée. ;La botaniste admire ce gland qui vient de la piner.
L'étudiante en archéologie rêve de tomber sur des fouilles curieuses. ;L'étudiante en archéologie rêve de tomber sur des couilles furieuses.
Un hachis parmentier. ;Un amant parti chier.
Elle est assise sur la berge du ravin.;Elle est assise sur la verge du rabbin.
Quel bonheur pour la princesse que la dotation du roi.;Quel bonheur pour la princesse que la rotation du doigt.
Les mutins passaient le berge du grand ravin.;Les putains massaient la verge du grand rabbin.
Saisons belles qui passent!;Baisons celles qui passent !
Le capitaine redoute les proues qui tuent. ;Le capitaine redoute les trous qui puent.
La pratique intensive du tennis en pension donne aux jeunes une mine piteuse.;La pratique intensive du pénis en tension donne aux jeunes une pine miteuse.
Il court, il court, le furet.;Il court, il fourre, le curé.
C'était une fine appellation.;C'était une pine à fellation.
C'est dimanche: un coup de vin.;Un coup de manche: c'est divin.
Un petit calcul et on s'en va.;Un petit calva et on s'encule.
Le chercheur est fatigué après une belle thèse. ;Le chercheur est fatigué après une telle baise.
Les corbeaux aiment le sang qui coule à la curée d'un cerf.;Les corsaires aiment le sang qui coule à la raie d'un beau cul.
A l'évêché on peut voir un vieux plan de Gap.;A l'évêché on peut voir un vieux gland de pape
Elle est folle de la messe. ;Elle est molle de la fesse.
Salut Patrick!;Ca pue la trique!
Les luxations répétées provoquent la fêlure.;Les fellations répétées provoquent la luxure.
A force de mouiller les fiches, je suis arrivé au fond de la colle.;A force de fouiller les miches, je suis arrivé au con de la folle.
A la boutique des Milles Bottes, on solde des tennis de pro.;A la boutique des belles mottes, on solde des pénis de trop.
A l'armée, le lieutenant veut défiler et le général m'engueule!;A l'armée, le lieutenant veut dégueuler et le général m'enfile!
A l'auberge des Deux Reines, le cuisinier entame une vache marginale.;A l'auberge des Nœuds Raides, le cuisinier entame une marche vaginale.
A l'auberge du Congre Debout, j'ai humé des Côtes en fût et j'ai senti des rillettes du cru.;A l'auberge du Bougre de Con, j'ai humé des crottes de cul et j'ai senti des filles en rut.
A l'auberge du Congre Debout, j'ai mangé de la tourte aux cailles et je me suis délectée d'une vieille fine sans dépôt.;A l'auberge du Bougre de Con, j'ai mangé de la tarte aux couilles et je me suis délectée d'une vieille pine sans défaut.
Faites donc voir votre glu à l'ancienne: cette vielle colle s'enflamme au contact des feux.;Faites donc voir votre gland à Lucienne: cette vielle folle s'enflamme au contact des queues.
A l'hôtel du Bon Coucher, j'ai goûté un vieux marc très doux et j'ai apprécié la poire à la fine.;A l'hôtel du Con Bouché, j'ai goûté un vieux dard très mou et j'ai apprécié la foire à la pine.
A l'idée de voir la Chine, la jeune fille est envahie d'une étrange pâleur.;A l'idée de voir la pine, la jeune fille est envahie d'une étrange chaleur.
A quoi bon me pousser pour que je vous trompe?;A quoi bon me trousser pour que je vous pompe?
A vouloir aller plus vite que le son, vous risquez de vous briser la nuque!;A vouloir aller plus vite que le con, vous risquez de vous briser l'anus!
A Wimbledon, le juge de touche s'est fait acculer derrière Sanchez.;A Wimbledon, le juge de touche s'est fait enculer derrière sa chaise.
Madame, admirez donc l'écaille de ces moules!;Madame, admirez donc les couilles de ces mâles!
Adjudant, faites bisser l'appel!;Adjudant, faites pisser la belle!
Ah Madame! Si vous saviez ce que votre plante me fait!;Ah Madame! si vous saviez ce que votre fente me plaît!
Ah! Ma sœur! Vous avez bêché trois allées?! ;Ah! Ma sœur! Vous avez léché trois abbés?!
Aimer le blanc, c'est une histoire de goût.;Aimer le gland, c'est une histoire de bout.
Les religieuses se lèvent au couchant et se passent facilement de pain jusqu'aux matines.;Les religieuses se lèchent au couvent et se passent facilement de pine jusqu'au matin.
Après de pareils faits, vous pouvez vous permettre.;Après de pareils pets, vous pouvez vous faire mettre.
Apprendre à calculer en cent leçons.;Apprendre à s'enculer en caleçon.

View file

@ -1,449 +0,0 @@
# -*- coding: utf-8 -*-
"""Main module."""
from __future__ import unicode_literals
import aiocron
import asyncio
import discord
import giphy_client
import gitlab
import logging
import lxml
import os
import random
import requests
import configparser
import argparse
import typing
import functools
from bs4 import BeautifulSoup as bs
from discord.ext import tasks, commands
from giphy_client.rest import ApiException
from logging.handlers import RotatingFileHandler
from pathlib import Path
from subprocess import *
from sys import argv,exit, exc_info
here = os.path.dirname(os.path.abspath(__file__))
class Texte(commands.Cog):
#class Mybot(discord.Client):
#Fonctions necesaires pour Kabot.
def __init__(
self,
bot,
intents=None,
gl_url=None,
gl_token=None,
gif_token=None,
audio_path=None,
nickname=None,
voice_chan=None,
text_chan=None,
):
self.gl_url = gl_url
self.gl_token = gl_token
self.gif_token = gif_token
self.voice_chan = voice_chan
self.text_chan = text_chan
self.bot = bot
self.nickname = nickname
@commands.Cog.listener()
async def on_ready(self):
for channel in self.bot.get_all_channels():
if channel.name == self.text_chan:
current_chan = channel
if self.nickname:
await self.bot.user.edit(nick=self.nickname)
await current_chan.send('Le troll est dans la place !')
self.kron.start()
@commands.Cog.listener()
async def on_message(self, message):
if message.author == self.bot.user and message.content.startswith('!'):
if message.content.startswith('!'):
ctx = await self.bot.get_context(message)
await self.bot.invoke(ctx)
return
else:
if self.bot.user in message.mentions \
and len(message.mentions) < 3 \
and len(message.content.splitlines()) == 1:
path = '/data/log/%s.log' % message.channel
with open(path, 'r') as f:
lines = f.read().splitlines()
if not message.content in lines:
with open(path, 'a') as f:
f.write(message.content + '\n')
response = random.choice(lines).replace(str(self.bot.user.id), str(message.author.id))
async with message.channel.typing():
if "http" in response:
await asyncio.sleep(len(response) / 8)
else:
await asyncio.sleep(len(response) / 6)
await message.channel.send(response)
#await self.bot.process_commands(message)
@commands.command(help='list des commits')
async def commits(self, ctx, number = 5):
try:
if self.gl_url and self.gl_token:
number = int(number)
gl = gitlab.Gitlab(self.gl_url, self.gl_token)
gl.auth()
projects = gl.projects.list(search='Kabot')[0]
commits = projects.commits.list(all=True)[:number]
for commit in commits:
detail = commit.attributes
await ctx.channel.send("__" + detail['author_name'] + "__: " + detail['title'] + '\n' + detail['web_url'])
else:
await ctx.channel.send("-_-")
except:
await ctx.channel.send("-_-")
@commands.command(help="Interrogation issues \n Args: list, search[mot clé] et add[nom de l'issue]")
async def issue(self, ctx, *args):
if self.gl_url and self.gl_token:
if args:
args = list(args)
gl = gitlab.Gitlab(self.gl_url, self.gl_token)
gl.auth()
if args[0] == 'list':
projects = gl.projects.list(search='Kabot')[0]
issues = projects.issues.list()
for issue in issues:
if "closed" == issue.state:
pass
else:
await ctx.channel.send('#' + str(issue.id) + ": " + issue.title + '\n' + issue.web_url)
elif args[0] == 'search':
query = ''.join(args[1:])
project = gl.projects.list(search='Kabot')[0]
find_issues = project.search("issues", query)
for issue in find_issues:
await ctx.channel.send("#" + str(issue['id']) + ": " + issue['title'] + '\n' + issue['web_url'])
elif args[0] == 'add':
title = ' '.join(args[1:])
author = title + ' - By ' + ctx.message.author.name
projects = gl.projects.list()
for project in projects:
if "Kabot" == project.name:
issue = project.issues.create({'title': author})
logger.info("Issue created : %s" % issue.web_url)
else:
await ctx.channel.send('unknown command')
@commands.command(help='count lines numbers in quote file')
async def lines(self, ctx):
path = '/data/log/%s.log' % ctx.channel
with open(path, 'r') as f:
lines = f.read().splitlines()
nb_lines = len(lines)
async with ctx.channel.typing():
await asyncio.sleep(0.5)
await ctx.channel.send("j'ai %s lignes dans mon stock" % nb_lines)
@commands.command(help='check if bot always online')
async def ping(self, message):
await message.channel.send('pong')
@commands.command(help='Restart Bot')
async def restart(self, ctx):
cmd = self.bot.get_command('leave')
await cmd.invoke(ctx)
await self.bot.close()
exit()
@commands.command(help='Update local repo')
async def update(self, message):
output = Popen('git pull'.split(), stdout=PIPE).communicate()[0]
cmd_audio = "git -C %s pull" % self.audio_path
output += Popen(cmd_audio.split(), stdout=PIPE).communicate()[0]
await message.channel.send(output.decode('utf-8'))
@commands.command(help="randomsur l'avenir des gens.")
async def avenir(self, ctx):
list_mot = ("tu seras curé, tu t'occuperas plus spécialement du catéchisme. ",
"tu seras animateur de soirées pour les gays pride. ",
"tu seras gynecologue dans une maison de retraite.",
"tu iras vivre en thaïland à cause de ton job. car tu seras ladyboy dans un bar.",
"tu sera DSI chez jacky et Michel",
"tu seras arroseur de plante aquatique.")
choix = random.choice(list_mot)
async with ctx.channel.typing():
await asyncio.sleep(len(choix) / 4)
await ctx.channel.send(choix)
@commands.command(help="j'adore la cuisine")
async def ciboulette(self, ctx):
cmd = self.bot.get_command('gif')
ctx.message.content = "!gif ciboulette"
await cmd.invoke(ctx)
@commands.command(help='Faire des choix')
async def choice(self, ctx, *words):
choices = random.choice(words)
await ctx.channel.send(choices)
@commands.command(help="optionnal args : ")
async def contrepeterie(self, ctx, *args):
response = None
path = here + '/ressources/contrepeteries.txt'
with open(path) as file:
lines = file.read().splitlines()
myline = random.choice(lines)
question, reponse = myline.split(";")
try:
response = '''Question ! : %s Réponse : ||%s||''' % (question, reponse)
except:
response = "Unknow error, try: !contrepeterie [mot clef]"
await ctx.send(response)
@commands.command(help='Gif me')
async def gif(self, ctx):
query = ctx.message.content.replace('!gif ', '')
api_instance = giphy_client.DefaultApi()
api_key = self.gif_token
lang = 'fr'
if api_key:
try:
api_response = api_instance.gifs_search_get(api_key, query, lang=lang, limit=15)
api_response.to_dict()['data'][0]
get_url = random.choice(api_response.to_dict()['data'])
get_url['url']
await ctx.channel.send(get_url['url'])
except ApiException as e:
await ctx.channel.send("Exception when calling DefaultApi->gifs_search_get: %s\n" % e)
else:
await ctx.channel.send("Exception : No api key found")
@commands.command(help="optionnal args : [livre] [character]")
async def kaamelott(self, ctx, *args):
response = None
url = 'https://kaamelott.chaudie.re/api/random'
if args and ctx.message.content:
args = list(args)
if args[0].isdigit():
livre = int(args[0])
args.pop(0)
elif args[-1].isdigit():
livre = int(args[-1])
args.pop(-1)
else:
livre = None
if args:
perso = ' '.join(args)
if perso and livre:
url = 'https://kaamelott.chaudie.re/api/random/livre/%s/personnage/%s' % (livre, perso)
elif perso:
url = 'https://kaamelott.chaudie.re/api/random/personnage/%s' % perso
else:
url = 'https://kaamelott.chaudie.re/api/random/livre/%s' % livre
try:
citation = requests.get(url).json()['citation']
response = "%s :\n```\n%s\n```" % (citation['infos']['personnage'], citation['citation'])
except:
response = "Unknow error, try: !kaamelott [livre] [character]"
await ctx.send(response)
@commands.command(help="Je menotte une cornemuse et je fume Eddy Malou")
async def kamoulox(self, ctx):
sans_verbe = get_word('nom').text + " " + get_word('complement').get('m') + " et " + get_word('nom').text + " " + get_word('complement').get('m') + "."
nom1 = get_word('nom')
nom2 = get_word('nom')
un1 = "un"
un2 = "un"
if nom1.get('gender') == 'F':
un1 = "une"
if nom2.get('gender') == 'F':
un2 = "une"
phrase1 = get_word('verbe').text + " " + un1 + " " + nom1.text + " " + random.choice([get_word('complement').get('m'), ""])
phrase2 = get_word('verbe').text + " " + un2 + " " + nom2.text + " " + random.choice([get_word('complement').get('m'), ""])
avec_verbe = phrase1 + " et " + phrase2 + "."
piece = random.choice(['pile', 'face'])
if piece == "pile":
result = sans_verbe
elif piece == "face":
result = avec_verbe
async with ctx.channel.typing():
await asyncio.sleep(len(result)/6)
await ctx.send(result)
@commands.dm_only()
@commands.command(help="Faire dire des choses au bot")
async def say(self, ctx, *message):
sentence = ' '.join(message)
channel = [x for x in self.bot.get_all_channels() if x.name == self.text_chan][0]
guild = self.bot.guilds[0]
for word in sentence.split():
if word.startswith('@'):
members = guild.members
for member in members:
if member.display_name.lower() in word.lower():
sentence = sentence.replace(word, member.mention)
await channel.send(sentence)
@commands.command(help='Who the fuck am i?')
async def schizo(self, ctx, *names):
name = ' '.join(names)
list_name = ["Kabot", "Gaspard et Balthazar", "Bender", "Zoidberg", "Gunther", "MissSaugnacEtCambran2022"]
try:
current_name = self.bot.user.name
list_name.remove(current_name)
except:
pass
if not name:
name = random.choice(list_name)
lower_names = [x.lower() for x in list_name]
if name.lower() in lower_names:
if name:
correct_name = [x for x in list_name if x.lower() in name.lower()][0]
name = correct_name
await self.bot.user.edit(username=name)
else:
name = "404"
await self.bot.user.edit(username="Error 404 name not found!")
await ctx.channel.send("Liste des noms = %s" % list_name)
img = open(here + "/ressources/avatar_bot/%s.jpg" % name, 'rb')
await self.bot.user.edit(avatar=img.read())
await self.joke(ctx, name)
@tasks.loop(seconds=3600)
async def kron(self):
kron_choice = random.choice([self.kaamelott, self.slap, self.kamoulox, self.contrepeterie, self.schizo, None, None, None, None, None, None, None,None,None,None,None,None,None])
if kron_choice != None:
await asyncio.sleep(random.choice(range(3550)))
for channel in self.bot.get_all_channels():
if channel.name == self.text_chan:
current_chan = channel
async for msg in current_chan.history(limit=1):
last_message = msg
ctx = await self.bot.get_context(last_message)
ctx.message.content = ""
await kron_choice(ctx)
@commands.command(help='slap this ass')
async def slap(self, ctx, user=None):
slap_multiple = [
"%s prend un coup de pied au cul",
"Descente du coude sur %s",
"%s est propulsé par dessus la TROISIEME CORDE!",
"Le mec en rose, c'est moi et le mec en jaune c'est %s! https://giphy.com/gifs/gSIz6gGLhguOY",
]
if not user or not ctx.message.mentions:
online_members = []
members = ctx.guild.members
for member in members:
if str(member.status) == "online":
online_members.append(member)
user = random.choice(online_members)
user = user.mention
elif ctx.message.mentions:
user = ctx.message.mentions[0]
user = user.mention
if user == self.bot.user.mention:
async with ctx.channel.typing():
await asyncio.sleep(0.5)
await ctx.channel.send("je tribuche par terre et je sais pas comment")
else:
async with ctx.channel.typing():
await asyncio.sleep(len(slap_multiple) / 4)
await ctx.channel.send(random.choice(slap_multiple) % user)
#Commandes pour troll.
@commands.command(help='Troll commands', hidden=True)
async def jke(self, ctx):
await ctx.channel.send(trollpower())
@commands.command(help='Troll commands', hidden=True)
async def joe(self, ctx):
await ctx.channel.send(trollpower())
@commands.command(help='Troll commands', hidden=True)
async def jok(self, ctx):
await ctx.channel.send(trollpower())
@commands.command(help='Troll commands', hidden=True)
async def joker(self, ctx):
await ctx.channel.send(trollpower(too_long=True))
@commands.command(help='Troll commands', hidden=True)
async def oke(self, ctx):
await ctx.channel.send(trollpower())
def trollpower(too_long=None):
if too_long:
return("Bah alors, on sait plus écrire, je te donne un indice: t'as une lettre en trop! :sweat_drops: :tongue:")
return('Bah alors, on sait plus écrire, je te donne un indice: il te manque une lettre! :sweat_drops: :tongue:')
def get_word(word_type):
"""Chercher les mots pour la fonction kamoulox dans le fichier xml"""
content = []
with open(here + "/ressources/base_kml.xml", "r", encoding="ISO-8859-1") as file:
content = file.readlines()
content = "".join(content)
bs_content = bs(content, 'lxml')
if word_type == 'nom':
nom = bs_content.resources.nom.find_all('word')
result = random.choice(nom)
return result
elif word_type == 'nom_propre':
nom_propre = bs_content.resources.nompropre.find_all('word')
result = random.choice(nom_propre)
return result
elif word_type == 'verbe':
verbe = bs_content.resources.verbe.find_all('word')
result = random.choice(verbe)
return result
elif word_type == 'complement':
complement = bs_content.resources.complement.find_all('word')
result = random.choice(complement)
return result
elif word_type == 'nom_special':
nom_special = bs_content.resources.complement.find_all('word')
result = random.choice(nom_special)
return result
elif word_type == 'prenom':
prenom = bs_content.resources.prenom.find_all('word')
result = random.choice(prenom)
return result
elif word_type == 'prescuse':
prescuse = bs_content.resources.prescuse.find_all('word')
result = random.choice(prescuse)
return result
elif word_type == 'scuse1':
scuse1 = bs_content.resources.scuse1.find_all('word')
result = random.choice(scuse1)
return result
elif word_type == 'scuse2':
scuse2 = bs_content.resources.scuse2.find_all('word')
result = random.choice(scuse2)
return result
elif word_type == 'presulte':
presulte = bs_content.resources.presulte.find_all('word')
result = random.choice(presulte)
return result
elif word_type == 'sulte':
sulte = bs_content.resources.sulte.find_all('word')
result = random.choice(sulte)
return result
elif word_type == 'postsulte':
postsulte = bs_content.resources.presulte.find_all('word')
result = random.choice(postsulte)
return result
elif word_type == 'mail':
mail = bs_content.resources.mail.find_all('word')
result = random.choice(mail)
return result
else:
result = 'Nique bien ta mère!'
return result

View file

@ -0,0 +1,10 @@
pip==19.2.3
bump2version==0.5.11
wheel==0.33.6
watchdog==0.9.0
flake8==3.7.8
tox==3.14.0
coverage==4.5.4
Sphinx==1.8.5
twine==1.14.0

View file

@ -15,12 +15,6 @@ requirements = [
'discord.py', 'discord.py',
'requests', 'requests',
'PyNaCl', 'PyNaCl',
'aiocron',
'python-gitlab',
'giphy_client',
'yt-dlp',
'lxml',
'BeautifulSoup4',
] ]
setup_requirements = [ ] setup_requirements = [ ]
@ -30,7 +24,7 @@ test_requirements = [ ]
setup( setup(
author="Michaël Ricart", author="Michaël Ricart",
author_email='michael.ricart@0w.tf', author_email='michael.ricart@0w.tf',
python_requires='>=3.11', python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
classifiers=[ classifiers=[
'Development Status :: 2 - Pre-Alpha', 'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
@ -46,14 +40,13 @@ setup(
description="kabot for discord", description="kabot for discord",
entry_points={ entry_points={
'console_scripts': [ 'console_scripts': [
'kabot=kabot.kabot:run', 'kabot=kabot.kabot:main',
], ],
}, },
install_requires=requirements, install_requires=requirements,
license="BSD license", license="BSD license",
long_description=readme + '\n\n' + history, long_description=readme + '\n\n' + history,
include_package_data=True, include_package_data=True,
package_data={'ressources': ['kabot/utils/ressources/*']},
keywords='kabot', keywords='kabot',
name='kabot', name='kabot',
packages=find_packages(include=['kabot', 'kabot.*']), packages=find_packages(include=['kabot', 'kabot.*']),
@ -61,6 +54,6 @@ setup(
test_suite='tests', test_suite='tests',
tests_require=test_requirements, tests_require=test_requirements,
url='https://github.com/None/kabot', url='https://github.com/None/kabot',
version='0.2.18', version='0.1.0',
zip_safe=False, zip_safe=False,
) )

20
kabot/tox.ini Normal file
View file

@ -0,0 +1,20 @@
[tox]
envlist = py27, py35, py36, py37 flake8
[travis]
python =
3.7: py37
3.6: py36
3.5: py35
2.7: py27
[testenv:flake8]
basepython = python
deps = flake8
commands = flake8 kabot
[testenv]
setenv =
PYTHONPATH = {toxinidir}
commands = python setup.py test

37
pinned.cfg Normal file
View file

@ -0,0 +1,37 @@
[versions]
Click = 7.0
Jinja2 = 2.10.1
MarkupSafe = 1.1.1
aiohttp = 3.5.4
async-timeout = 3.0.1
attrs = 19.1.0
binaryornot = 0.4.4
certifi = 2019.9.11
chardet = 3.0.4
cookiecutter = 1.6.0
future = 0.17.1
idna = 2.8
jinja2-time = 0.2.0
mr.developer = 2.0.0
multidict = 4.5.2
poyo = 0.5.0
requests = 2.22.0
urllib3 = 1.25.6
websockets = 6.0
whichcraft = 0.6.1
yarl = 1.3.0
zc.buildout = 2.13.2
zc.recipe.egg = 2.0.7
# Required by:
# jinja2-time==0.2.0
arrow = 0.15.2
# Required by:
# arrow==0.15.2
python-dateutil = 2.8.0
# Required by:
# mr.developer==2.0.0
six = 1.12.0