This commit is contained in:
Azaria
2026-02-19 17:45:54 +00:00
commit bbb42896ba
33 changed files with 9956 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace App;
use Illuminate\Support\Facades\Route;
use Laracord\Laracord;
class Bot extends Laracord
{
/**
* The HTTP routes.
*/
public function routes(): void
{
Route::middleware('web')->group(function () {
// Route::get('/', fn () => 'Hello world!');
});
Route::middleware('api')->group(function () {
// Route::get('/commands', fn () => collect($this->registeredCommands)->map(fn ($command) => [
// 'signature' => $command->getSignature(),
// 'description' => $command->getDescription(),
// ]));
});
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace App\Events;
use Discord\Discord;
use Discord\Parts\Channel\Message;
use Discord\WebSockets\Event as Events;
use Laracord\Events\Event;
class MessageCreate extends Event
{
/**
* The event handler.
*
* @var string
*/
protected $handler = Events::MESSAGE_CREATE;
/**
* Handle the event.
*/
public function handle(Message $message, Discord $discord)
{
$this->console()->log('The Message Create event has fired!');
}
}
+72
View File
@@ -0,0 +1,72 @@
<?php
namespace App\Events;
use App\Models\Emote;
use App\Models\User;
use Discord\Discord;
use Discord\Parts\WebSockets\MessageReaction;
use Discord\WebSockets\Event as Events;
use Laracord\Events\Event;
class MessageReactionAdd extends Event
{
/**
* The event handler.
*
* @var string
*/
protected $handler = Events::MESSAGE_REACTION_ADD;
/**
* Handle the event.
*/
public function handle(MessageReaction $reaction, Discord $discord)
{
if ($reaction->user->bot || ! $reaction->guild_id) {
return;
}
if ($reaction->emoji && $reaction->emoji->id) {
if ($reaction->emoji->guild_id) {
if ($reaction->emoji->guild_id !== $reaction->guild_id) {
return;
}
} else {
$guild = $discord->guilds->get('id', $reaction->guild_id);
if (! $guild || ! $guild->emojis->get('id', $reaction->emoji->id)) {
return;
}
}
}
$user = User::firstOrCreate(
['discord_id' => $reaction->user_id],
['username' => $reaction->user->username]
);
$emoteId = $reaction->emoji->id ?? $reaction->emoji->name;
$type = $reaction->emoji->id ? ($reaction->emoji->animated ? 'ANIMATED' : 'STATIC') : 'UNICODE';
$guildId = $reaction->guild_id;
$emote = Emote::firstOrCreate(
['emote_id' => $emoteId],
[
'guild_id' => $guildId,
'emote_name' => $reaction->emoji->name,
'type' => $type,
]
);
$emote->addReaction(
user: $user,
guildId: $reaction->guild_id,
channelId: $reaction->channel_id,
messageId: $reaction->message_id,
unicodeEmoji: boolval($reaction->emoji->id) ? null : $reaction->emoji->name
);
}
}
+64
View File
@@ -0,0 +1,64 @@
<?php
namespace App\Events;
use App\Models\Emote;
use App\Models\User;
use Discord\Discord;
use Discord\Parts\WebSockets\MessageReaction;
use Discord\WebSockets\Event as Events;
use Laracord\Events\Event;
class MessageReactionRemove extends Event
{
/**
* The event handler.
*
* @var string
*/
protected $handler = Events::MESSAGE_REACTION_REMOVE;
/**
* Handle the event.
*/
public function handle(MessageReaction $reaction, Discord $discord)
{
if ($reaction->user->bot || ! $reaction->guild_id) {
return;
}
if ($reaction->emoji && $reaction->emoji->id) {
if ($reaction->emoji->guild_id) {
if ($reaction->emoji->guild_id !== $reaction->guild_id) {
return;
}
} else {
$guild = $discord->guilds->get('id', $reaction->guild_id);
if (! $guild || ! $guild->emojis->get('id', $reaction->emoji->id)) {
return;
}
}
}
$user = User::where('discord_id', $reaction->user_id)->first();
if (! $user) {
return;
}
$emoteId = $reaction->emoji->id ?? $reaction->emoji->name;
$emote = Emote::where('emote_id', $emoteId)
->where('guild_id', $reaction->guild_id)
->first();
if ($emote) {
$emote->removeReaction(
$user,
$reaction->guild_id,
$reaction->message_id,
boolval($reaction->emoji->id) ? null : $reaction->emoji->name
);
}
}
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace App\Events;
use App\Models\EmoteGuildStat;
use App\Models\EmoteLog;
use Discord\Discord;
use Discord\Parts\WebSockets\MessageReaction;
use Discord\WebSockets\Event as Events;
use Laracord\Events\Event;
class MessageReactionRemoveAll extends Event
{
/**
* The event handler.
*
* @var string
*/
protected $handler = Events::MESSAGE_REACTION_REMOVE_ALL;
/**
* Handle the event.
*/
public function handle(MessageReaction $reaction, Discord $discord)
{
if ($reaction->user->bot || ! $reaction->guild_id) {
return;
}
if ($reaction->emoji && $reaction->emoji->id) {
if ($reaction->emoji->guild_id) {
if ($reaction->emoji->guild_id !== $reaction->guild_id) {
return;
}
} else {
$guild = $discord->guilds->get('id', $reaction->guild_id);
if (! $guild || ! $guild->emojis->get('id', $reaction->emoji->id)) {
return;
}
}
}
$logs = EmoteLog::where('message_id', $reaction->message->id)
->where('guild_id', $reaction->message->guild_id)
->get();
foreach ($logs as $log) {
EmoteGuildStat::where([
'emote_id' => $log->emote_id,
'guild_id' => $log->guild_id,
])->decrement('usage_count');
}
EmoteLog::where('message_id', $reaction->message->id)
->where('guild_id', $reaction->message->guild_id)
->delete();
}
}
+108
View File
@@ -0,0 +1,108 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Emote extends Model
{
protected $fillable = [
'emote_id',
'guild_id',
'emote_name',
'type',
];
protected $casts = [
'emote_id' => 'string',
'guild_id' => 'string',
];
public function logs()
{
return $this->hasMany(
EmoteLog::class,
'emote_id',
'emote_id'
);
}
public function guildStats()
{
return $this->hasMany(
EmoteGuildStat::class,
'emote_id',
'emote_id'
);
}
public function scopeForGuild($query, $guildId)
{
return $query->where('guild_id', $guildId);
}
public function addReaction(User $user, string $guildId, string $channelId, string $messageId, ?string $unicodeEmoji = null)
{
$exists = EmoteLog::where([
'emote_id' => $this->emote_id,
'user_id' => $user->discord_id,
'guild_id' => $guildId,
'message_id' => $messageId,
'emoji_unicode' => boolval($unicodeEmoji),
])->exists();
if ($exists) {
return;
}
EmoteLog::create([
'emote_id' => $this->emote_id,
'user_id' => $user->discord_id,
'guild_id' => $guildId,
'channel_id' => $channelId,
'message_id' => $messageId,
'emoji_unicode' => boolval($unicodeEmoji),
]);
if ($unicodeEmoji === null) {
EmoteGuildStat::firstOrCreate(
['emote_id' => $this->emote_id, 'guild_id' => $guildId],
['usage_count' => 0]
)->increment('usage_count');
}
UserGuildStat::firstOrCreate(
[
'user_id' => $user->discord_id,
'guild_id' => $guildId,
'emote_id' => $this->emote_id,
],
[
'usage_count' => 0,
'emote_id' => $this->emote_id,
]
)->increment('usage_count');
}
public function removeReaction(User $user, string $guildId, string $messageId, ?string $unicodeEmoji = null)
{
$deleted = EmoteLog::where([
'emote_id' => $this->emote_id,
'user_id' => $user->discord_id,
'guild_id' => $guildId,
'message_id' => $messageId,
'emoji_unicode' => boolval($unicodeEmoji),
])->delete();
if ($deleted) {
if ($unicodeEmoji === null) {
EmoteGuildStat::where(['emote_id' => $this->emote_id, 'guild_id' => $guildId])
->decrement('usage_count');
}
UserGuildStat::where(['user_id' => $user->discord_id, 'guild_id' => $guildId])
->decrement('usage_count');
}
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class EmoteGuildStat extends Model
{
protected $fillable = [
'emote_id',
'guild_id',
'usage_count',
];
protected $casts = [
'emote_id' => 'string',
'guild_id' => 'string',
];
public function emote()
{
return $this->belongsTo(
Emote::class,
'emote_id',
'emote_id'
);
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class EmoteLog extends Model
{
protected $fillable = [
'emote_id',
'user_id',
'guild_id',
'channel_id',
'message_id',
'emoji_unicode',
];
protected $casts = [
'emote_id' => 'string',
'guild_id' => 'string',
'channel_id' => 'string',
'message_id' => 'string',
'emoji_unicode' => 'boolean',
];
public function emote()
{
return $this->belongsTo(
Emote::class,
'emote_id',
'emote_id'
);
}
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'discord_id');
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Sanctum\HasApiTokens;
class User extends Model
{
use HasApiTokens;
protected $fillable = [
'username',
'discord_id',
'is_admin',
];
protected $casts = [
'is_admin' => 'boolean',
'discord_id' => 'string',
];
public function emoteLogs()
{
return $this->hasMany(EmoteLog::class, 'user_id', 'discord_id');
}
public function emotes()
{
return $this->hasManyThrough(
Emote::class,
EmoteLog::class,
'user_id',
'emote_id',
'discord_id',
'emote_id'
);
}
public function hasUsedEmote($emoteId): bool
{
return $this->emoteLogs()
->where('emote_id', $emoteId)
->exists();
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UserGuildStat extends Model
{
protected $fillable = [
'user_id',
'guild_id',
'emote_id',
'usage_count',
];
protected $casts = [
'user_id' => 'string',
'guild_id' => 'string',
'emote_id' => 'string',
];
public function user()
{
return $this->belongsTo(User::class, 'user_id', 'discord_id');
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Providers;
use Laracord\LaracordServiceProvider;
class BotServiceProvider extends LaracordServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
parent::boot();
if (env('APP_ENV') === 'development') {
\DB::listen(function ($query) {
$sql = $query->sql;
$bindings = json_encode($query->bindings);
$time = $query->time;
$log = '['.date('Y-m-d H:i:s')."] SQL: $sql | Bindings: $bindings | Time: {$time}ms\n";
$logPath = storage_path('logs/query.log');
file_put_contents($logPath, $log, FILE_APPEND);
});
}
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
parent::register();
}
}