update
Цей коміт міститься в:
4
.gitignore
сторонній
Звичайний файл
4
.gitignore
сторонній
Звичайний файл
@@ -0,0 +1,4 @@
|
||||
vendor/
|
||||
|
||||
*.log
|
||||
public/states/*.json
|
||||
28
Dockerfile
Звичайний файл
28
Dockerfile
Звичайний файл
@@ -0,0 +1,28 @@
|
||||
FROM php:apache
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y libzip-dev
|
||||
RUN docker-php-ext-install zip
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
COPY public/ public
|
||||
COPY src/ src
|
||||
COPY app.php app.php
|
||||
COPY README.md README.md
|
||||
COPY composer.json composer.json
|
||||
COPY composer.lock composer.lock
|
||||
|
||||
# Application
|
||||
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||
RUN composer install --no-dev
|
||||
|
||||
# Apache
|
||||
COPY docker/vhost.conf /etc/apache2/sites-available/project.conf
|
||||
RUN a2enmod rewrite &&\
|
||||
a2dissite 000-default &&\
|
||||
a2ensite project &&\
|
||||
service apache2 restart
|
||||
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["bash", "-c", "apache2-foreground & php app.php"]
|
||||
33
README.md
33
README.md
@@ -1,3 +1,36 @@
|
||||
# VoiceState - Discord Bot
|
||||
This is a simple bot, tracking the mute state of members currently using the voice chat. The generated json files are named by the userId and contain just the mute state and no other information.
|
||||
|
||||
## Example
|
||||
```
|
||||
# https://discordbot.f-brinker.de/voice-state/states/userId123.json
|
||||
{"state":"selfMuted"}
|
||||
```
|
||||
|
||||
### Possible States
|
||||
* active
|
||||
* muted
|
||||
* selfMuted
|
||||
|
||||
## Usage
|
||||
* Add the Bot to your Discord Guild: [Add VoiceState Bot](https://discord.com/api/oauth2/authorize?client_id=954772647575703602&permissions=0&scope=bot)
|
||||
* Grab the state by fetching https://discordbot.f-brinker.de/voice-state/states/userId123.json
|
||||
* Replace userId123 with your Discord userId
|
||||
|
||||
## Host your own!
|
||||
You can host your own bot by building the project on your own or by using the pre-built image `fbrinker/discordbot-voice-state`.
|
||||
|
||||
You need to create your own Discord application and bot. You need the Bot Token below. Replace `yourBotToken` with your actual token.
|
||||
|
||||
### Examle Docker-Compose
|
||||
```
|
||||
discordbot-voice-state:
|
||||
container_name: discordbot-voice-state
|
||||
image: fbrinker/discordbot-voice-state
|
||||
restart: always
|
||||
environment:
|
||||
- "BOT_TOKEN=yourBotToken"
|
||||
```
|
||||
|
||||
## Contribute
|
||||
Feel free to add Pull-Request @ https://git.f-brinker.de/fbrinker/discordbot-voice-state
|
||||
|
||||
46
app.php
Звичайний файл
46
app.php
Звичайний файл
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
error_reporting(E_ALL ^ E_DEPRECATED);
|
||||
ini_set('memory_limit', '128M');
|
||||
|
||||
include __DIR__.'/vendor/autoload.php';
|
||||
|
||||
use \Monolog\Logger;
|
||||
use \Monolog\Handler\ErrorLogHandler;
|
||||
use \Monolog\Handler\RotatingFileHandler;
|
||||
|
||||
use Discord\Discord;
|
||||
use Discord\WebSockets\Intents;
|
||||
use Discord\WebSockets\Event;
|
||||
use Discord\Parts\WebSockets\VoiceStateUpdate;
|
||||
|
||||
use VoiceState\Bot;
|
||||
|
||||
$botToken = getenv("BOT_TOKEN");
|
||||
if (empty($botToken)) {
|
||||
die("Missing BOT_TOKEN");
|
||||
}
|
||||
|
||||
$logger = new Logger(Bot::NAME);
|
||||
$logger->pushHandler(new ErrorLogHandler(ErrorLogHandler::SAPI, Logger::INFO));
|
||||
$logger->pushHandler(new RotatingFileHandler(__DIR__ . '/logs/' . Bot::NAME . ".log", Bot::MAX_LOG_FILE_COUNT, Logger::WARNING));
|
||||
|
||||
$bot = new Bot(__DIR__ . '/public/states/', $logger);
|
||||
|
||||
$discord = new Discord([
|
||||
'token' => $botToken,
|
||||
'intents' => [
|
||||
Intents::GUILD_VOICE_STATES
|
||||
],
|
||||
'logger' => $logger
|
||||
]);
|
||||
|
||||
$discord->on('ready', function (Discord $discord) use ($logger) {
|
||||
$logger->info("Bot is ready!");
|
||||
});
|
||||
|
||||
$discord->on(Event::VOICE_STATE_UPDATE, function (VoiceStateUpdate $state, Discord $discord, $oldstate) use ($bot, $logger) {
|
||||
$logger->info('Event: ' . Event::VOICE_STATE_UPDATE);
|
||||
$bot->updateVoiceState($state);
|
||||
});
|
||||
|
||||
$discord->run();
|
||||
14
composer.json
Звичайний файл
14
composer.json
Звичайний файл
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"VoiceState\\": "src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"team-reflex/discord-php": "dev-master",
|
||||
"league/commonmark": "^2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-latest"
|
||||
}
|
||||
}
|
||||
3468
composer.lock
згенерований
Звичайний файл
3468
composer.lock
згенерований
Звичайний файл
Різницю між файлами не показано, бо вона завелика
Завантажити різницю
3
docker/vhost.conf
Звичайний файл
3
docker/vhost.conf
Звичайний файл
@@ -0,0 +1,3 @@
|
||||
<VirtualHost *:80>
|
||||
DocumentRoot /var/www/html/public
|
||||
</VirtualHost>
|
||||
0
logs/.gitkeep
Звичайний файл
0
logs/.gitkeep
Звичайний файл
9
public/index.php
Звичайний файл
9
public/index.php
Звичайний файл
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
//error_reporting(0);
|
||||
|
||||
include __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
$converter = new CommonMarkConverter();
|
||||
echo $converter->convert(file_get_contents(__DIR__ . '/../README.md'));
|
||||
0
public/states/.gitkeep
Звичайний файл
0
public/states/.gitkeep
Звичайний файл
76
src/Bot.php
Звичайний файл
76
src/Bot.php
Звичайний файл
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace VoiceState;
|
||||
|
||||
use \Monolog\Logger;
|
||||
use Discord\Parts\WebSockets\VoiceStateUpdate;
|
||||
|
||||
class Bot
|
||||
{
|
||||
public const NAME = "VoiceState";
|
||||
public const MAX_LOG_FILE_COUNT = 7;
|
||||
private const STATE_FILE_TEMPLATE = "%s.json";
|
||||
|
||||
private const STATE_DEFAULT = [
|
||||
'state' => null,
|
||||
];
|
||||
private const STATE_ACTIVE = 'active';
|
||||
private const STATE_MUTE = 'muted';
|
||||
private const STATE_SELF_MUTE = 'selfMuted';
|
||||
|
||||
private string $stateFileDir;
|
||||
private Logger $logger;
|
||||
|
||||
public function __construct(string $stateFileDir, Logger $logger)
|
||||
{
|
||||
if (!is_dir($stateFileDir)) {
|
||||
throw new \RuntimeException("stateFileDir is no directory");
|
||||
}
|
||||
|
||||
$this->stateFileDir = rtrim($stateFileDir, '/');
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function updateVoiceState(VoiceStateUpdate $voiceState): void
|
||||
{
|
||||
try {
|
||||
$stateFile = $this->stateFileDir . '/' . sprintf(self::STATE_FILE_TEMPLATE, $voiceState->user_id);
|
||||
|
||||
if (!file_exists($stateFile)) {
|
||||
$this->createStatusFile($stateFile);
|
||||
}
|
||||
|
||||
$state = $this->getState($voiceState);
|
||||
file_put_contents($stateFile, json_encode($state));
|
||||
} catch (\Throwable $t) {
|
||||
$this->logger->error($t);
|
||||
}
|
||||
}
|
||||
|
||||
private function getState(VoiceStateUpdate $voiceState)
|
||||
{
|
||||
$state = self::STATE_DEFAULT;
|
||||
$state['state'] = self::STATE_ACTIVE;
|
||||
if ($voiceState->mute) {
|
||||
$state['state'] = self::STATE_MUTE;
|
||||
}
|
||||
if ($voiceState->self_mute) {
|
||||
$state['state'] = self::STATE_SELF_MUTE;
|
||||
}
|
||||
|
||||
return $state;
|
||||
}
|
||||
|
||||
private function createStatusFile(string $stateFile): void
|
||||
{
|
||||
if (file_exists($stateFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
file_put_contents($stateFile, json_encode(self::STATE_DEFAULT));
|
||||
|
||||
if (!file_exists($stateFile)) {
|
||||
throw new \RuntimeException("could not create statefile: " . $stateFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
Посилання в новій задачі
Заблокувати користувача