Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb2f677a0f | ||
|
|
533eba17d2 | ||
|
|
7d7a68bc38 | ||
|
|
9106c08c95 | ||
|
|
3b4bdac5df | ||
|
|
70a11d7216 | ||
|
|
b44e832146 | ||
|
|
efea057cf2 | ||
|
|
5612ff02b2 | ||
|
|
8e851d890e | ||
|
|
c6532aa640 | ||
|
|
bc63ee1a04 | ||
|
|
d3be8ea543 | ||
|
|
d0724764dd | ||
|
|
528651681b | ||
|
|
71a696f21d | ||
|
|
0205ce03d8 | ||
|
|
2898bc2afd | ||
|
|
946c7382e5 | ||
|
|
e9e26cbe89 | ||
|
|
5e098345d3 | ||
|
|
57184f0b21 | ||
|
|
b8cbe8c80c | ||
|
|
9e6a89fe78 | ||
|
|
78d3c42040 | ||
|
|
c354ca6362 | ||
|
|
0306f11305 | ||
|
|
3668ea7d98 | ||
|
|
534050a991 | ||
|
|
2893f516dc | ||
|
|
be20e90f08 | ||
|
|
7ce95509df | ||
|
|
9feb5b9a3c | ||
|
|
1f994a6e7f | ||
|
|
0698d093a6 | ||
|
|
e890a561ed | ||
|
|
03c4de805c | ||
|
|
b738111b5e | ||
|
|
03e3e6f692 |
@@ -10,3 +10,5 @@ run.sh
|
||||
runtime.txt
|
||||
Pipfile
|
||||
Pipfile.lock
|
||||
pyproject.toml
|
||||
poetry.lock
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
liberapay: marcpartensky
|
||||
patreon: marcpartensky
|
||||
github: marcpartensky
|
||||
custom:
|
||||
# - monero:43J2XmRtjDPRLD35UsYGH2AZamFBQz7dt4VdvZXVm3SuadTrvcoXUXBRUNHqukFte23Q5TWXqhbwaLJJgoVQzzbe2AJDANQ
|
||||
- https://paypal.me/marcpartensky
|
||||
- https://buymeacoffee.com/marcpartensky
|
||||
|
||||
@@ -32,12 +32,18 @@ jobs:
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
- name: Build and push with tag
|
||||
id: tag-build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: marcpartensky/discord-bot:v${{ github.run_number }}.${{ steps.tag.outputs.tag }}
|
||||
- name: Build and push latest
|
||||
id: latest-build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: marcpartensky/discord-bot:latest
|
||||
|
||||
test-python-versions:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- master
|
||||
|
||||
env:
|
||||
IMAGE_NAME: discord-bot
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push latest
|
||||
id: latest-build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: false
|
||||
tags: marcpartensky/discord-bot:latest
|
||||
|
||||
test-python-versions:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
python-version: ['3.8', '3.9', '3.10']
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: pip
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ hashFiles('setup.py') }}-${{ hashFiles('requirements.txt') }}
|
||||
- name: Install requirements
|
||||
run: pip install -r requirements.txt
|
||||
- name: Display Python version
|
||||
run: python -c "import sys; print(sys.version)"
|
||||
|
||||
@@ -8,3 +8,4 @@ venv/
|
||||
.env
|
||||
.env.dev
|
||||
./config/marc_store.yml
|
||||
.python-version
|
||||
|
||||
+30
-1
@@ -1,4 +1,4 @@
|
||||
FROM python:3.8.12-slim
|
||||
FROM python:3.8.13-slim as ubuntu
|
||||
LABEL maintainer="marc.partensky@gmail.com"
|
||||
LABEL image="https://hub.docker.com/r/marcpartensky/discord-bot"
|
||||
LABEL source="https://github.com/marcpartensky/discord-bot"
|
||||
@@ -24,3 +24,32 @@ ENV DISCORD_BOT_PORT 8000
|
||||
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD curl -f http://localhost:8000/live || exit 1
|
||||
|
||||
ENTRYPOINT ["python", "__main__.py"]
|
||||
|
||||
|
||||
FROM python:3.8.13-alpine as alpine
|
||||
LABEL maintainer="marc.partensky@proton.me"
|
||||
LABEL image="https://hub.docker.com/r/marcpartensky/discord-bot"
|
||||
LABEL source="https://github.com/marcpartensky/discord-bot"
|
||||
RUN apk update
|
||||
RUN apk add ffmpeg git gcc g++ gfortran musl musl-dev build-base cmake openblas pkgconfig
|
||||
# RUN apk add ffmpeg git py3-scikit-learn
|
||||
COPY requirements.txt ./
|
||||
|
||||
RUN pip install -U pip
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./tts tts
|
||||
COPY ./libs libs
|
||||
COPY ./assets assets
|
||||
COPY ./utils utils
|
||||
COPY ./config config
|
||||
COPY ./models models
|
||||
COPY ./cogs cogs
|
||||
COPY __main__.py LICENSE ./
|
||||
|
||||
ENV DISCORD_BOT_HOST 0.0.0.0
|
||||
ENV DISCORD_BOT_PORT 8000
|
||||
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD curl -f http://localhost:8000/live || exit 1
|
||||
|
||||
ENTRYPOINT ["python", "__main__.py"]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
start:
|
||||
pipenv run python .
|
||||
poetry run python .
|
||||
update:
|
||||
pipenv lock --pre --clear
|
||||
pipenv lock -r > requirements.txt
|
||||
poetry update
|
||||
poetry export --output requirements.txt
|
||||
dev:
|
||||
docker-compose -f docker-compose.yml up -d --build --force-recreate --remove-orphans dev
|
||||
prod:
|
||||
@@ -14,12 +14,8 @@ push: build
|
||||
deploy: push
|
||||
DOCKER_HOST=ssh://vps docker service update vps_esclave
|
||||
setup:
|
||||
pip install pipenv
|
||||
pipenv shell
|
||||
pipenv install
|
||||
poetry install
|
||||
poetry shell
|
||||
recreate:
|
||||
docker-compose -f docker-compose.yml up --force-recreate dev
|
||||
fixwithbrew:
|
||||
brew install python@3.8
|
||||
sudo ln -sf /home/linuxbrew/.linuxbrew/Cellar/python@3.8/3.8.12_1/bin/python3.8 /usr/bin/python3.8
|
||||
|
||||
|
||||
Generated
-1445
File diff suppressed because it is too large
Load Diff
+14
-4
@@ -17,7 +17,7 @@ from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from config.config import prefix, masters, delete_after_time, status, access
|
||||
from config.config import prefix, masters, access
|
||||
from config.credentials import token, client_id
|
||||
from discord.ext import commands, tasks
|
||||
|
||||
@@ -31,6 +31,9 @@ from discord.ext import commands, tasks
|
||||
# # Notice how you can use spaces in prefixes. Try to keep them simple though.
|
||||
# prefixes = ['>?', 'lol ', '!?']
|
||||
|
||||
|
||||
|
||||
|
||||
# # Check to see if we are outside of a guild. e.g DM's etc.
|
||||
# if not message.guild:
|
||||
# # Only allow ? to be used in DMs
|
||||
@@ -39,8 +42,6 @@ from discord.ext import commands, tasks
|
||||
# # If we are in a guild, we allow for the user to mention us or use any of the prefixes in our list.
|
||||
# return commands.when_mentioned_or(*prefixes)(bot, message)
|
||||
|
||||
client = commands.Bot(command_prefix=prefix, case_insensitive=True)
|
||||
client.id = client_id
|
||||
|
||||
|
||||
class Main(commands.Cog):
|
||||
@@ -56,7 +57,7 @@ class Main(commands.Cog):
|
||||
self.load_cogs()
|
||||
self.load_status()
|
||||
self.load_icloud()
|
||||
self.api: PycloudService = None
|
||||
# self.api: PycloudService = None
|
||||
|
||||
def load_icloud(self):
|
||||
"""Charge l'api d'icloud."""
|
||||
@@ -79,6 +80,7 @@ class Main(commands.Cog):
|
||||
@commands.command()
|
||||
async def environment(self, ctx: commands.Context):
|
||||
"""Affiche l'environnement dans lequel le bot tourne."""
|
||||
print("environment")
|
||||
host = os.environ.get("HOST")
|
||||
await ctx.send(f"> Environment: **{host}**")
|
||||
|
||||
@@ -96,6 +98,7 @@ class Main(commands.Cog):
|
||||
for i, filename in enumerate(cogs):
|
||||
bar.update(i)
|
||||
if filename.endswith(".py"):
|
||||
print(filename)
|
||||
self.bot.load_extension(f"cogs.{filename[:-3]}")
|
||||
|
||||
@commands.command()
|
||||
@@ -280,5 +283,12 @@ def setup(bot: commands.Bot):
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.system("clear")
|
||||
print("prefix:", prefix)
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
|
||||
# client = commands.Bot(command_prefix=prefix, case_insensitive=True)
|
||||
client = commands.Bot(command_prefix=prefix, intents=intents)
|
||||
client.id = client_id
|
||||
setup(client)
|
||||
client.run(token)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import discord
|
||||
import os
|
||||
import dotenv
|
||||
from discord.ext import commands
|
||||
|
||||
dotenv.load_dotenv()
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
bot = commands.Bot(command_prefix=">", intents=intents)
|
||||
|
||||
# bot = discord.Bot()
|
||||
|
||||
@bot.command()
|
||||
async def hello(ctx, name: str = None):
|
||||
name = name or ctx.author.name
|
||||
await ctx.respond(f"Hello {name}!")
|
||||
|
||||
@bot.command(name="Say Hello")
|
||||
async def hi(ctx, user):
|
||||
await ctx.respond(f"{ctx.author.mention} says hello to {user.name}!")
|
||||
|
||||
@bot.command()
|
||||
async def ping(ctx):
|
||||
await ctx.send("pong")
|
||||
|
||||
bot.run(os.environ["DISCORD_TOKEN"])
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/bin/env python
|
||||
|
||||
# from config.config import masters, access, check
|
||||
# from config import shops
|
||||
# from utils import tools
|
||||
|
||||
from config.config import access, cluster
|
||||
from discord.ext import commands
|
||||
|
||||
import discord
|
||||
import os
|
||||
import psycopg2
|
||||
|
||||
|
||||
class Backup(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""Setup postgres logins"""
|
||||
self.bot = bot
|
||||
self.host = os.environ.get("POSTGRES_HOST")
|
||||
self.port = os.environ.get("POSTGRES_PORT")
|
||||
self.database = os.environ.get("POSTGRES_DATABASE")
|
||||
self.user = os.environ.get("POSTGRES_USER")
|
||||
self.password = os.environ.get("POSTGRES_PASSWORD")
|
||||
self.color = 0x0064a5
|
||||
self.connection: psycopg2.connection
|
||||
self.cursor: psycopg2.cursor
|
||||
|
||||
|
||||
@commands.command(name="postgres-connect")
|
||||
@access.admin
|
||||
async def connect_postgres(self, ctx: commands.Context):
|
||||
"""Change les identifiants postgres avec un string user,password,database,host,port."""
|
||||
self.connection = psycopg2.connect(
|
||||
user=self.user,
|
||||
password=self.password,
|
||||
host=self.host,
|
||||
port=self.port,
|
||||
database=self.database
|
||||
)
|
||||
self.cursor = self.connection.cursor()
|
||||
await ctx.send("Connected to the database")
|
||||
|
||||
@commands.command(name="postgres-set")
|
||||
@access.admin
|
||||
async def set_postgres_logins(self, ctx: commands.Context, connection: str):
|
||||
"""Change les identifiants postgres avec un string user,password,database,host,port."""
|
||||
|
||||
try:
|
||||
self.user, self.password, self.database, self.host, self.port = connection.split(",")
|
||||
except:
|
||||
return await ctx.send("> Le format doit être le suivant: user,password,database,host,port")
|
||||
embed = discord.Embed(
|
||||
title="PostgreSQL logins", color=discord.Color(self.color)
|
||||
)
|
||||
embed.add_field(name="user", value=self.user)
|
||||
embed.add_field(name="password", value=self.password)
|
||||
embed.add_field(name="database", value=self.database)
|
||||
embed.add_field(name="host", value=self.host)
|
||||
embed.add_field(name="port", value=self.port)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="postgres")
|
||||
@access.admin
|
||||
async def get_postgres_logins(self, ctx: commands.Context):
|
||||
"""Affiche les identifiants postgres uniquement si master"""
|
||||
embed = discord.Embed(
|
||||
title="PostgreSQL Logins", color=discord.Color(self.color)
|
||||
)
|
||||
embed.add_field(name="user", value=self.user)
|
||||
embed.add_field(name="password", value=self.password)
|
||||
embed.add_field(name="database", value=self.database)
|
||||
embed.add_field(name="host", value=self.host)
|
||||
embed.add_field(name="port", value=self.port)
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Backup(bot))
|
||||
+3
-6
@@ -1,14 +1,11 @@
|
||||
from config.config import access, status, delete_after_time, masters, link
|
||||
from config import emoji
|
||||
from config.config import access, delete_after_time, link
|
||||
|
||||
from utils.date import days, months
|
||||
from utils import tools
|
||||
|
||||
from discord.ext import commands, tasks
|
||||
from discord.ext import commands
|
||||
from translate import Translator
|
||||
from discord.utils import get
|
||||
from discord import Message, PartialEmoji, Emoji
|
||||
from bs4 import BeautifulSoup
|
||||
from discord import Message, PartialEmoji
|
||||
import requests
|
||||
import datetime
|
||||
import discord
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
"""Use groq"""
|
||||
|
||||
import typing
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord.ext.commands.core import has_role
|
||||
|
||||
from utils.tools import create_role_if_missing, Capturing
|
||||
|
||||
import sys
|
||||
import asyncio, os
|
||||
from websockets.sync.client import connect
|
||||
|
||||
GROQ_ROLE = "Groq"
|
||||
|
||||
|
||||
class Groq(commands.Cog):
|
||||
"""Control Groq shells"""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""Initialize the cog with the bot."""
|
||||
self.host = "localhost"
|
||||
self.port = 8765
|
||||
self.bot = bot
|
||||
self.color: discord.Color = discord.Color.darker_grey()
|
||||
self.thumbnail: str = "https://wow.groq.com/wp-content/uploads/2021/04/groq-logo.svg"
|
||||
self.shells: typing.Dict[int, dict] = {}
|
||||
# self.timeout = 3600
|
||||
|
||||
# @commands.command(name="groq-shells")
|
||||
# async def groq_shells(self, ctx: commands.Context):
|
||||
# """List opened shells."""
|
||||
# if len(self.shells) == 0:
|
||||
# return await ctx.send("> No shell opened.")
|
||||
# embed = discord.Embed(title="Shells :", color=self.color)
|
||||
# embed.set_thumbnail(url=self.thumbnail)
|
||||
|
||||
# shell_users = []
|
||||
# for shell_user in map(self.bot.fetch_user, self.shells.keys()):
|
||||
# shell_users.append(f"- {await shell_user}")
|
||||
# embed.description = "\n".join(shell_users)
|
||||
# await ctx.send(embed=embed)
|
||||
|
||||
@commands.Cog.listener(name="on_message")
|
||||
async def on_message(self, msg: discord.Message):
|
||||
"""Read all messages"""
|
||||
if msg.author == self.bot.user:
|
||||
return
|
||||
if msg.content.startswith(self.bot.command_prefix):
|
||||
return
|
||||
if self.hash(msg) in self.shells:
|
||||
answer = await self.ask(msg, msg.content)
|
||||
await msg.channel.send(answer)
|
||||
|
||||
|
||||
# async def cog_common_error(self, ctx, error):
|
||||
# """Close all shell sessions."""
|
||||
# for shell in self.shells.values():
|
||||
# shell.close()
|
||||
|
||||
@commands.command()
|
||||
async def groq(self, ctx: commands.Context):
|
||||
"""Go in groq mode."""
|
||||
key = self.hash(ctx)
|
||||
# Create a role if in guild
|
||||
if ctx.guild:
|
||||
await create_role_if_missing(ctx, GROQ_ROLE, self.color)
|
||||
embed = discord.Embed(color=self.color)
|
||||
embed.set_thumbnail(url=self.thumbnail)
|
||||
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar)
|
||||
# embed.description = self.shell_path
|
||||
|
||||
if ctx.author.id in self.shells:
|
||||
shell = self.shells[key]
|
||||
del self.shells[key]
|
||||
embed.title = "Closed shell"
|
||||
await ctx.send(embed=embed)
|
||||
else:
|
||||
embed.title = "Opened shell"
|
||||
await ctx.send(embed=embed)
|
||||
self.shells[key] = dict(messages=[])
|
||||
|
||||
def hash(self, ctx):
|
||||
"""Make a unique hash with channel id and author."""
|
||||
print(ctx.author.id, ctx.channel.id)
|
||||
print(self.shells)
|
||||
return hash((ctx.author.id, ctx.channel.id))
|
||||
|
||||
def build_prompt(self, messages: list) -> str:
|
||||
"""Build prompt."""
|
||||
prompt = ""
|
||||
for (me, bot) in messages:
|
||||
prompt += f"me: {me}\n"
|
||||
prompt += f"you: {bot}\n"
|
||||
return prompt
|
||||
|
||||
async def ask(self, ctx, message: str) -> str:
|
||||
"""Return groq answer"""
|
||||
key = self.hash(ctx)
|
||||
prompt = self.build_prompt(self.shells[key]["messages"])
|
||||
prompt += f"me: {message}\n"
|
||||
prompt += "answer my last message"
|
||||
with connect(f"ws://{self.host}:{self.port}") as websocket:
|
||||
websocket.send(prompt)
|
||||
answer = str(websocket.recv())
|
||||
print(f"{prompt} => {answer}")
|
||||
self.shells[key]["messages"].append((message, answer))
|
||||
return answer
|
||||
|
||||
|
||||
def setup(bot):
|
||||
"""Setup the Shell cog."""
|
||||
bot.add_cog(Groq(bot))
|
||||
@@ -0,0 +1,66 @@
|
||||
"""
|
||||
All sound effects you want in one command.
|
||||
"""
|
||||
|
||||
import time
|
||||
import datetime
|
||||
import discord
|
||||
|
||||
from utils.date import months, days
|
||||
from config.config import cluster, masters
|
||||
from discord.ext import commands
|
||||
|
||||
|
||||
class Record(commands.Cog):
|
||||
"""Record voices."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""Define the recorder"""
|
||||
# self.sounds = cluster.sound_deck.sounds
|
||||
self.bot = bot
|
||||
self.connections = {}
|
||||
|
||||
# @property
|
||||
# def music(self):
|
||||
# return self.bot.get_cog("Music")
|
||||
|
||||
# @commands.group(name="son", aliases=["sound", "sn"])
|
||||
# async def sound(self, ctx: commands.Context):
|
||||
# """Groupe des commandes pour un son."""
|
||||
# if not ctx.invoked_subcommand:
|
||||
# return await ctx.send(
|
||||
# f"> Commande inexistante."
|
||||
# f"\n> Écrivez `{ctx.bot.command_prefix}help son` pour voir les commandes disponibles."
|
||||
# ""
|
||||
# )
|
||||
|
||||
# @sound.command(name="voir", aliases=["v", "show", "see"])
|
||||
# async def show(self, ctx: commands.Context, *, name: str):
|
||||
# """Affiche un son."""
|
||||
# embed = self.embed_sound(name)
|
||||
# await ctx.send(embed=embed)
|
||||
|
||||
|
||||
@commands.command(name="record")
|
||||
async def record(self, ctx): # If you're using commands.Bot, this will also work.
|
||||
"""Enregistre une voix."""
|
||||
voice = ctx.author.voice
|
||||
|
||||
if not voice:
|
||||
await ctx.respond("You aren't in a voice channel!")
|
||||
|
||||
vc = await voice.channel.connect() # Connect to the voice channel the author is in.
|
||||
self.connections.update({ctx.guild.id: vc}) # Updating the cache with the guild and channel.
|
||||
|
||||
vc.start_recording(
|
||||
discord.sinks.WaveSink(), # The sink type to use.
|
||||
self.once_done, # What to do once done.
|
||||
ctx.channel # The channel to disconnect from.
|
||||
)
|
||||
await ctx.respond("Started recording!")
|
||||
|
||||
def once_done(self, *args):
|
||||
print("its done", args)
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Record(bot))
|
||||
@@ -69,7 +69,7 @@ class VoiceChannel(commands.Cog):
|
||||
logging.info(before)
|
||||
channel: discord.VoiceChannel = before.channel
|
||||
members: List[discord.Member] = channel.members
|
||||
await self.mute_if_single(members)
|
||||
# await self.mute_if_single(members)
|
||||
await self.leave_if_alone(members, before.channel)
|
||||
|
||||
async def join(
|
||||
@@ -83,7 +83,7 @@ class VoiceChannel(commands.Cog):
|
||||
logging.info(after)
|
||||
channel: discord.VoiceChannel = after.channel
|
||||
members: List[discord.Member] = channel.members
|
||||
await self.mute_if_single(members)
|
||||
# await self.mute_if_single(members)
|
||||
await self.notify_on_join(member)
|
||||
await self.join_if_single(members)
|
||||
|
||||
@@ -102,7 +102,7 @@ class VoiceChannel(commands.Cog):
|
||||
before_members: List[discord.Member] = before_channel.members
|
||||
after_channel: discord.VoiceChannel = after.channel
|
||||
after_members: List[discord.Member] = after_channel.members
|
||||
await self.mute_if_single(before_members)
|
||||
# await self.mute_if_single(before_members)
|
||||
await self.join_if_single(after_members)
|
||||
|
||||
async def mute_if_single(self, members: List[discord.Member]):
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ link = "https://discordapp.com/oauth2/authorize?&client_id=703347349623144549&sc
|
||||
prefix = os.environ.get("DISCORD_PREFIX") or "."
|
||||
masters = [478552571510915072] # , 219949869220102147]
|
||||
wolfram = wolframalpha.Client(wolfram_alpha_id)
|
||||
ialab_bot_url = "https://ialab.marcpartensky.com"
|
||||
ialab_bot_url = os.environ.get("IALAB_URL") or "https://ialab.marcpartensky.com"
|
||||
|
||||
roles = ["@Maître", "@Admin"]
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile
|
||||
target: ubuntu
|
||||
ports:
|
||||
- "8000:8000"
|
||||
env_file:
|
||||
@@ -21,5 +22,6 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./Dockerfile
|
||||
target: alpine
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
+19
-12
@@ -1,5 +1,4 @@
|
||||
# from mongocollection import MongoCollection
|
||||
import discord
|
||||
from pymongo import MongoClient
|
||||
from pymongo.database import Database
|
||||
from pymongo.collection import Collection, ObjectId
|
||||
@@ -102,7 +101,7 @@ class MongoCluster(MongoClient):
|
||||
def __getitem__(self, item):
|
||||
"""Return a mongo database given its key."""
|
||||
item = super().__getitem__(item)
|
||||
if isinstance(item, pymongo.database.Database):
|
||||
if isinstance(item, Database):
|
||||
return MongoDatabase.from_database(item)
|
||||
else:
|
||||
return item
|
||||
@@ -120,7 +119,7 @@ class MongoDatabase(Database):
|
||||
def __getitem__(self, item):
|
||||
"""Return a mongo collection given a key."""
|
||||
item = super().__getitem__(item)
|
||||
if isinstance(item, pymongo.collection.Collection):
|
||||
if isinstance(item, Collection):
|
||||
return MongoCollection.from_collection(item)
|
||||
else:
|
||||
return item
|
||||
@@ -201,10 +200,10 @@ class MongoCollection(Collection):
|
||||
else:
|
||||
self.insert_one(arg, **kwargs)
|
||||
|
||||
def insert_many(self, posts, **kwargs):
|
||||
def insert_many(self, posts):
|
||||
"""Insert many posts."""
|
||||
posts = [self.treat(post) for post in posts]
|
||||
super().insert_many(post)
|
||||
super().insert_many(posts)
|
||||
|
||||
def __contains__(self, id):
|
||||
return self.seek_one(_id=id) != None
|
||||
@@ -241,10 +240,9 @@ class MongoCollection(Collection):
|
||||
|
||||
def __delitem__(self, id):
|
||||
"""Delete a post."""
|
||||
print(id)
|
||||
print(self.find_one(dict(_id=id)))
|
||||
# print(self.find_one(dict(_id=id)))
|
||||
self.delete_one(dict(_id=id))
|
||||
print(self.find_one(dict(_id=id)))
|
||||
# print(self.find_one(dict(_id=id)))
|
||||
|
||||
def post(self, post):
|
||||
"""Replace or insert a post."""
|
||||
@@ -264,12 +262,14 @@ class MongoCollection(Collection):
|
||||
"""Set a default post."""
|
||||
if id in self:
|
||||
post.update(self[id]._dict)
|
||||
print(1, post)
|
||||
# print(1, post)
|
||||
self[id] = post
|
||||
print(2, self[id])
|
||||
# print(2, self[id])
|
||||
|
||||
def __setattr__(self, att, value):
|
||||
if att in type(self).keys or att in dir(self):
|
||||
"""Set attribute to a collection."""
|
||||
# print(att, value)
|
||||
if att in type(self).keys or att in dir(self) or att.startswith("_"):
|
||||
super().__setattr__(att, value)
|
||||
else:
|
||||
self.__setitem__(att, value)
|
||||
@@ -497,7 +497,14 @@ class User(DictObject):
|
||||
# command = db.commands.find(machin=34, bidule=324)
|
||||
|
||||
if __name__ == "__main__":
|
||||
mongo_url = "mongodb+srv://esclave:esclave@discord-cluster-5ckni.mongodb.net/test"
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
cluster = os.environ["DISCORD_MONGO_CLUSTER"]
|
||||
username = os.environ["DISCORD_MONGO_USERNAME"]
|
||||
password = os.environ["DISCORD_MONGO_PASSWORD"]
|
||||
mongo_url = f"mongodb+srv://{username}:{password}@{cluster}"
|
||||
cl = MongoCluster(mongo_url)
|
||||
# print('cluster over')
|
||||
esclave = cl.esclave
|
||||
|
||||
Generated
+2536
File diff suppressed because it is too large
Load Diff
+21
-12
@@ -1,11 +1,17 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
[tool.poetry]
|
||||
name = "discord-bot"
|
||||
version = "0.1.0"
|
||||
description = "A discord bot multi purpose."
|
||||
authors = ["Marc Partensky <marc.partensky@gmail.com>"]
|
||||
license = "GPL2"
|
||||
readme = "README.md"
|
||||
packages = [{include = "discord_bot"}]
|
||||
|
||||
[packages]
|
||||
[tool.poetry.dependencies]
|
||||
python = "3.8.13"
|
||||
# python = "3.8-dev"
|
||||
beautifulsoup4 = "*"
|
||||
"discord.py[voice]" = "*"
|
||||
# "discord.py[voice]" = "*"
|
||||
fbchat = "*"
|
||||
# fbchat = {git = "git://github.com/carpedm20/fbchat.git"}
|
||||
nightcore = "*"
|
||||
@@ -36,11 +42,14 @@ unidecode = '*'
|
||||
future = '*'
|
||||
selenium = "*"
|
||||
fake-useragent = "*"
|
||||
colorama = "*"
|
||||
# py-cord = "^2.4.1"
|
||||
psycopg2 = "*"
|
||||
py-cord = {extras = ["voice"], version = "^2.5.0"}
|
||||
groq = "^0.9.0"
|
||||
websockets = "^12.0"
|
||||
|
||||
[dev-packages]
|
||||
black = "*"
|
||||
pylint = "*"
|
||||
jedi = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.8.12"
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
+1389
-85
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
from enum import Enum
|
||||
|
||||
import discord
|
||||
import os
|
||||
import dotenv
|
||||
from discord import Forbidden
|
||||
|
||||
dotenv.load_dotenv()
|
||||
|
||||
bot = discord.Bot(debug_guilds=["Beta"])
|
||||
connections = {}
|
||||
|
||||
|
||||
class Sinks(Enum):
|
||||
mp3 = discord.sinks.MP3Sink()
|
||||
wav = discord.sinks.WaveSink()
|
||||
pcm = discord.sinks.PCMSink()
|
||||
ogg = discord.sinks.OGGSink()
|
||||
mka = discord.sinks.MKASink()
|
||||
mkv = discord.sinks.MKVSink()
|
||||
mp4 = discord.sinks.MP4Sink()
|
||||
m4a = discord.sinks.M4ASink()
|
||||
|
||||
|
||||
async def finished_callback(sink, channel: discord.TextChannel, *args):
|
||||
recorded_users = [f"<@{user_id}>" for user_id, audio in sink.audio_data.items()]
|
||||
await sink.vc.disconnect()
|
||||
files = [
|
||||
discord.File(audio.file, f"{user_id}.{sink.encoding}")
|
||||
for user_id, audio in sink.audio_data.items()
|
||||
]
|
||||
await channel.send(
|
||||
f"Finished! Recorded audio for {', '.join(recorded_users)}.", files=files
|
||||
)
|
||||
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def get_channels(ctx, id):
|
||||
try:
|
||||
guild = await bot.get_guild(id)
|
||||
except Forbidden:
|
||||
await ctx.send("I do not have access to that guild or it doesn't exist.")
|
||||
else:
|
||||
for channel in guild.channels:
|
||||
print(channel.id)
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def start(ctx: discord.ApplicationContext, sink: Sinks):
|
||||
"""Record your voice!"""
|
||||
voice = ctx.author.voice
|
||||
|
||||
if not voice:
|
||||
return await ctx.respond("You're not in a vc right now")
|
||||
|
||||
vc = await voice.channel.connect()
|
||||
connections.update({ctx.guild.id: vc})
|
||||
|
||||
vc.start_recording(
|
||||
sink.value,
|
||||
finished_callback,
|
||||
ctx.channel,
|
||||
)
|
||||
|
||||
await ctx.respond("The recording has started!")
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def stop(ctx: discord.ApplicationContext):
|
||||
"""Stop recording."""
|
||||
if ctx.guild.id in connections:
|
||||
vc = connections[ctx.guild.id]
|
||||
vc.stop_recording()
|
||||
del connections[ctx.guild.id]
|
||||
await ctx.delete()
|
||||
else:
|
||||
await ctx.respond("Not recording in this guild.")
|
||||
|
||||
|
||||
bot.run(os.environ["DISCORD_TOKEN"])
|
||||
@@ -0,0 +1,141 @@
|
||||
import io
|
||||
|
||||
import pydub # pip install pydub==0.25.1
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord.sinks import MP3Sink
|
||||
import os
|
||||
import dotenv
|
||||
dotenv.load_dotenv()
|
||||
|
||||
PREFIX = "."
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.members = True
|
||||
intents.message_content = True
|
||||
|
||||
# bot = commands.Bot(
|
||||
# command_prefix=PREFIX,
|
||||
# intents=intents,
|
||||
# )
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
|
||||
# client = commands.Bot(command_prefix=prefix, case_insensitive=True)
|
||||
bot = commands.Bot(command_prefix=PREFIX, intents=intents)
|
||||
# setup(client)
|
||||
|
||||
# bot = discord.Bot(command_prefix=PREFIX)
|
||||
|
||||
|
||||
|
||||
@bot.event
|
||||
async def on_ready():
|
||||
print(f"Logged in as {bot.user}")
|
||||
|
||||
@bot.command()
|
||||
async def answer(ctx: discord.ApplicationContext):
|
||||
"""answer"""
|
||||
await ctx.respond("answer!")
|
||||
|
||||
|
||||
async def finished_callback(sink: MP3Sink, channel: discord.TextChannel):
|
||||
mention_strs = []
|
||||
audio_segs: list[pydub.AudioSegment] = []
|
||||
files: list[discord.File] = []
|
||||
|
||||
longest = pydub.AudioSegment.empty()
|
||||
|
||||
for user_id, audio in sink.audio_data.items():
|
||||
mention_strs.append(f"<@{user_id}>")
|
||||
|
||||
seg = pydub.AudioSegment.from_file(audio.file, format="mp3")
|
||||
|
||||
# Determine the longest audio segment
|
||||
if len(seg) > len(longest):
|
||||
audio_segs.append(longest)
|
||||
longest = seg
|
||||
else:
|
||||
audio_segs.append(seg)
|
||||
|
||||
audio.file.seek(0)
|
||||
files.append(discord.File(audio.file, filename=f"{user_id}.mp3"))
|
||||
|
||||
for seg in audio_segs:
|
||||
longest = longest.overlay(seg)
|
||||
|
||||
with io.BytesIO() as f:
|
||||
longest.export(f, format="mp3")
|
||||
await channel.send(
|
||||
f"Finished! Recorded audio for {', '.join(mention_strs)}.",
|
||||
files=files + [discord.File(f, filename="recording.mp3")],
|
||||
)
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def join(ctx: discord.ApplicationContext):
|
||||
"""Join the voice channel!"""
|
||||
voice = ctx.author.voice
|
||||
|
||||
if not voice:
|
||||
return await ctx.respond("You're not in a vc right now")
|
||||
|
||||
await voice.channel.connect()
|
||||
|
||||
await ctx.respond("Joined!")
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def start(ctx: discord.ApplicationContext):
|
||||
"""Record the voice channel!"""
|
||||
voice = ctx.author.voice
|
||||
|
||||
if not voice:
|
||||
return await ctx.respond("You're not in a vc right now")
|
||||
|
||||
vc: discord.VoiceClient = ctx.voice_client
|
||||
|
||||
if not vc:
|
||||
return await ctx.respond(
|
||||
"I'm not in a vc right now. Use `/join` to make me join!"
|
||||
)
|
||||
|
||||
vc.start_recording(
|
||||
MP3Sink(),
|
||||
finished_callback,
|
||||
ctx.channel,
|
||||
sync_start=True, # WARNING: This feature is very unstable and may break at any time.
|
||||
)
|
||||
|
||||
await ctx.respond("The recording has started!")
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def stop(ctx: discord.ApplicationContext):
|
||||
"""Stop the recording"""
|
||||
vc: discord.VoiceClient = ctx.voice_client
|
||||
|
||||
if not vc:
|
||||
return await ctx.respond("There's no recording going on right now")
|
||||
|
||||
vc.stop_recording()
|
||||
|
||||
await ctx.respond("The recording has stopped!")
|
||||
|
||||
|
||||
@bot.command()
|
||||
async def leave(ctx: discord.ApplicationContext):
|
||||
"""Leave the voice channel!"""
|
||||
vc: discord.VoiceClient = ctx.voice_client
|
||||
|
||||
if not vc:
|
||||
return await ctx.respond("I'm not in a vc right now")
|
||||
|
||||
await vc.disconnect()
|
||||
|
||||
await ctx.respond("Left!")
|
||||
|
||||
|
||||
bot.run(os.environ["DISCORD_TOKEN"])
|
||||
Reference in New Issue
Block a user