├── .env ├── tsconfig.json ├── src ├── database │ └── mongoose.ts ├── utils │ └── embed.ts ├── models │ ├── shop.ts │ ├── inventory.ts │ └── economy.ts ├── commands │ ├── market.ts │ ├── günlük.ts │ ├── envanter.ts │ ├── bakiye.ts │ ├── yardım.ts │ ├── satin-al.ts │ ├── calis.ts │ ├── transfer.ts │ ├── siralama.ts │ └── admin.ts └── index.ts ├── package.json └── README.md /.env: -------------------------------------------------------------------------------- 1 | TOKEN= 2 | MONGODB_URI= 3 | ADMIN_IDS= -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "commonjs", 5 | "outDir": "./dist", 6 | "rootDir": "./src", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["src/**/*"], 12 | "exclude": ["node_modules"] 13 | } -------------------------------------------------------------------------------- /src/database/mongoose.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | import * as dotenv from 'dotenv'; 3 | 4 | dotenv.config(); 5 | 6 | const MONGODB_URI = process.env.MONGODB_URI || ''; 7 | 8 | export async function connectToDatabase() { 9 | try { 10 | await mongoose.connect(MONGODB_URI); 11 | console.log('MongoDB veritabanına başarıyla bağlandı!'); 12 | } catch (error) { 13 | console.error('MongoDB bağlantı hatası:', error); 14 | process.exit(1); 15 | } 16 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lyra", 3 | "version": "1.0.0", 4 | "type": "commonjs", 5 | "main": "src/index.ts", 6 | "scripts": { 7 | "dev": "nodemon --watch src --ext ts,json --exec ts-node src/index.ts" 8 | }, 9 | "dependencies": { 10 | "discord.js": "^14.18.0", 11 | "dotenv": "^16.4.7", 12 | "mongoose": "^8.13.2" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^22.14.0", 16 | "nodemon": "^3.1.9", 17 | "ts-node": "^10.9.2", 18 | "typescript": "^5.8.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/utils/embed.ts: -------------------------------------------------------------------------------- 1 | import { EmbedBuilder, ColorResolvable } from 'discord.js'; 2 | 3 | export function createEmbed( 4 | title: string, 5 | description: string, 6 | color: ColorResolvable = '#0099ff' 7 | ): EmbedBuilder { 8 | return new EmbedBuilder() 9 | .setTitle(title) 10 | .setDescription(description) 11 | .setColor(color) 12 | .setTimestamp(); 13 | } 14 | 15 | export function createErrorEmbed(description: string): EmbedBuilder { 16 | return createEmbed('Hata', description, '#ff0000'); 17 | } 18 | 19 | export function createSuccessEmbed(description: string): EmbedBuilder { 20 | return createEmbed('Başarılı', description, '#00ff00'); 21 | } -------------------------------------------------------------------------------- /src/models/shop.ts: -------------------------------------------------------------------------------- 1 | import mongoose, { Schema, Document } from 'mongoose'; 2 | 3 | export interface IShopItem extends Document { 4 | guildId: string; 5 | name: string; 6 | description: string; 7 | price: number; 8 | role?: string; 9 | stock?: number; 10 | } 11 | 12 | const ShopItemSchema: Schema = new Schema({ 13 | guildId: { type: String, required: true }, 14 | name: { type: String, required: true }, 15 | description: { type: String, required: true }, 16 | price: { type: Number, required: true }, 17 | role: { type: String, default: null }, 18 | stock: { type: Number, default: -1 } 19 | }, { timestamps: true }); 20 | 21 | export const ShopItem = mongoose.model('ShopItem', ShopItemSchema); -------------------------------------------------------------------------------- /src/models/inventory.ts: -------------------------------------------------------------------------------- 1 | import mongoose, { Schema, Document } from 'mongoose'; 2 | 3 | export interface IInventory extends Document { 4 | userId: string; 5 | guildId: string; 6 | items: Array<{ 7 | itemId: mongoose.Types.ObjectId; 8 | quantity: number; 9 | purchasedAt: Date; 10 | }>; 11 | } 12 | 13 | const InventorySchema: Schema = new Schema({ 14 | userId: { type: String, required: true }, 15 | guildId: { type: String, required: true }, 16 | items: [{ 17 | itemId: { type: Schema.Types.ObjectId, ref: 'ShopItem' }, 18 | quantity: { type: Number, default: 1 }, 19 | purchasedAt: { type: Date, default: Date.now } 20 | }] 21 | }, { timestamps: true }); 22 | 23 | InventorySchema.index({ userId: 1, guildId: 1 }, { unique: true }); 24 | 25 | export const Inventory = mongoose.model('Inventory', InventorySchema); -------------------------------------------------------------------------------- /src/models/economy.ts: -------------------------------------------------------------------------------- 1 | import mongoose, { Schema, Document } from "mongoose"; 2 | 3 | export interface IEconomy extends Document { 4 | userId: string; 5 | guildId: string; 6 | balance: number; 7 | bank: number; 8 | lastDaily: Date; 9 | lastWork: Date; 10 | workCount: number; 11 | } 12 | 13 | const EconomySchema: Schema = new Schema({ 14 | userId: { type: String, required: true }, 15 | guildId: { type: String, required: true }, 16 | balance: { type: Number, default: 0 }, 17 | bank: { type: Number, default: 0 }, 18 | lastDaily: { type: Date, default: new Date(0) }, 19 | lastWork: { type: Date, default: new Date(0) }, 20 | workCount: { type: Number, default: 0 } 21 | }, { timestamps: true }); 22 | 23 | EconomySchema.index({ userId: 1, guildId: 1 }, { unique: true }); 24 | 25 | export const Economy = mongoose.model('Economy', EconomySchema); -------------------------------------------------------------------------------- /src/commands/market.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { CommandInteraction, EmbedBuilder } from 'discord.js'; 3 | import { ShopItem } from '../models/shop'; 4 | import { createEmbed, createErrorEmbed } from '../utils/embed'; 5 | 6 | export const data = new SlashCommandBuilder() 7 | .setName('market') 8 | .setDescription('Marketten alışveriş yapın'); 9 | 10 | export async function execute(interaction: CommandInteraction) { 11 | await interaction.deferReply(); 12 | 13 | const guildId = interaction.guildId; 14 | 15 | try { 16 | const shopItems = await ShopItem.find({ guildId }); 17 | 18 | if (shopItems.length === 0) { 19 | return interaction.editReply({ 20 | embeds: [createEmbed('Market', 'Markette şu anda hiç ürün yok.')] 21 | }); 22 | } 23 | 24 | const embed = new EmbedBuilder() 25 | .setTitle('Market') 26 | .setDescription('Aşağıdaki ürünleri `/satin-al [ürün adı]` komutu ile satın alabilirsiniz.') 27 | .setColor('#0099ff') 28 | .setTimestamp(); 29 | 30 | shopItems.forEach((item, index) => { 31 | const stockInfo = item.stock === -1 ? 'Sınırsız' : `${item.stock} adet`; 32 | embed.addFields({ 33 | name: `${index + 1}. ${item.name} - ${item.price} coin`, 34 | value: `${item.description}\nStok: ${stockInfo}${item.role ? `\nRol: <@&${item.role}>` : ''}` 35 | }); 36 | }); 37 | 38 | await interaction.editReply({ embeds: [embed] }); 39 | } catch (error) { 40 | console.error('Market komutu hatası:', error); 41 | await interaction.editReply({ embeds: [createErrorEmbed('Market bilgileri alınırken bir hata oluştu.')] }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/commands/günlük.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { CommandInteraction } from 'discord.js'; 3 | import { Economy } from '../models/economy'; 4 | import { createEmbed, createErrorEmbed } from '../utils/embed'; 5 | 6 | const DAILY_AMOUNT = 100; 7 | const COOLDOWN = 24 * 60 * 60 * 1000; 8 | 9 | export const data = new SlashCommandBuilder() 10 | .setName('günlük') 11 | .setDescription('Günlük coin ödülünüzü alın'); 12 | 13 | export async function execute(interaction: CommandInteraction) { 14 | await interaction.deferReply(); 15 | 16 | const userId = interaction.user.id; 17 | const guildId = interaction.guildId; 18 | 19 | try { 20 | let userEconomy = await Economy.findOne({ userId, guildId }); 21 | 22 | if (!userEconomy) { 23 | userEconomy = await Economy.create({ 24 | userId, 25 | guildId, 26 | balance: 0, 27 | bank: 0, 28 | lastDaily: new Date(0) 29 | }); 30 | } 31 | 32 | const now = new Date(); 33 | const lastDaily = new Date(userEconomy.lastDaily); 34 | const timeDiff = now.getTime() - lastDaily.getTime(); 35 | 36 | if (timeDiff < COOLDOWN) { 37 | const remainingTime = COOLDOWN - timeDiff; 38 | const hours = Math.floor(remainingTime / (1000 * 60 * 60)); 39 | const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60)); 40 | 41 | const nextAvailableTime = Date.now() + remainingTime; 42 | return interaction.editReply({ 43 | embeds: [createErrorEmbed(`Günlük ödülünüzü zaten aldınız! dakika sonra tekrar alabilirsiniz.`)] 44 | }); 45 | } 46 | 47 | userEconomy.balance += DAILY_AMOUNT; 48 | userEconomy.lastDaily = now; 49 | await userEconomy.save(); 50 | 51 | const embed = createEmbed( 52 | 'Günlük Ödül', 53 | `💰 **${DAILY_AMOUNT}** coin günlük ödülünüzü aldınız!\n\nYeni bakiyeniz: **${userEconomy.balance}** coin` 54 | ); 55 | 56 | await interaction.editReply({ embeds: [embed] }); 57 | } catch (error) { 58 | console.error('Günlük komut hatası:', error); 59 | await interaction.editReply({ embeds: [createErrorEmbed('Günlük ödül alınırken bir hata oluştu.')] }); 60 | } 61 | } -------------------------------------------------------------------------------- /src/commands/envanter.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { CommandInteraction, EmbedBuilder } from 'discord.js'; 3 | import { Inventory } from '../models/inventory'; 4 | import { ShopItem } from '../models/shop'; 5 | import { createEmbed, createErrorEmbed } from '../utils/embed'; 6 | import { Types } from 'mongoose'; 7 | 8 | export const data = new SlashCommandBuilder() 9 | .setName('envanter') 10 | .setDescription('Envanterinizi görüntüleyin') 11 | .addUserOption(option => 12 | option.setName('kullanici') 13 | .setDescription('Envanterini görmek istediğiniz kullanıcı') 14 | .setRequired(false)); 15 | 16 | export async function execute(interaction: CommandInteraction) { 17 | await interaction.deferReply(); 18 | 19 | const targetUser = interaction.options.get('kullanici')?.user || interaction.user; 20 | const guildId = interaction.guildId; 21 | 22 | try { 23 | const inventory = await Inventory.findOne({ userId: targetUser.id, guildId }); 24 | if (!inventory || inventory.items.length === 0) { 25 | return interaction.editReply({ 26 | embeds: [createEmbed(`${targetUser.username}'nin Envanteri`, 'Hiç eşya yok.')] 27 | }); 28 | } 29 | 30 | const embed = new EmbedBuilder() 31 | .setTitle(`${targetUser.username}'nin Envanteri`) 32 | .setDescription('Sahip olduğunuz eşyalar aşağıda listeleniyor.') 33 | .setColor('#0099ff') 34 | .setTimestamp(); 35 | 36 | for (const item of inventory.items) { 37 | const shopItem = await ShopItem.findById(item.itemId); 38 | if (!shopItem) continue; 39 | 40 | const purchaseDate = new Date(item.purchasedAt).toLocaleDateString('tr-TR'); 41 | embed.addFields({ 42 | name: `${shopItem.name} (${item.quantity} adet)`, 43 | value: `${shopItem.description}\nSatın alınma tarihi: ${purchaseDate}` 44 | }); 45 | } 46 | 47 | await interaction.editReply({ embeds: [embed] }); 48 | 49 | } catch (error) { 50 | console.log('Envanter komutu hatası:', error); 51 | await interaction.editReply({ embeds: [createErrorEmbed('Envanter bilgileri alınırken bir hata oluştu.')] }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lyra Ekonomi Botu 2 | 3 | Lyra, TypeScript ile geliştirilmiş, modern ve güçlü bir Discord botudur. MongoDB veritabanı entegrasyonu ile gelişmiş komut yapısına sahiptir. 4 | 5 | ## 🚀 Özellikler 6 | 7 | - TypeScript ile geliştirilmiş güvenli kod yapısı 8 | - MongoDB veritabanı entegrasyonu 9 | - Slash komut desteği 10 | - Gelişmiş hata yönetimi 11 | - Modern Discord.js v14 altyapısı 12 | 13 | ## 📋 Gereksinimler 14 | 15 | - Node.js (v16.9.0 veya üstü) 16 | - MongoDB veritabanı 17 | - Discord Bot Token 18 | - npm veya yarn 19 | 20 | ## ⚙️ Kurulum 21 | 22 | 1. Repoyu klonlayın: 23 | ```bash 24 | git clone https://github.com/erlly/lyra-ekonomi-botu.git 25 | cd Lyra 26 | ``` 27 | 28 | 2. Gerekli paketleri yükleyin: 29 | ```bash 30 | npm install 31 | # veya 32 | yarn install 33 | ``` 34 | 35 | 3. `.env` dosyasını oluşturun ve gerekli bilgileri ekleyin: 36 | ```env 37 | TOKEN=discord_bot_token_buraya 38 | MONGODB_URI=mongodb_baglanti_url_buraya 39 | ADMIN_IDS=kendi id'niz 40 | ``` 41 | 42 | 4. Botu başlatın: 43 | ```bash 44 | # Geliştirme modu için 45 | npm run dev 46 | # veya 47 | yarn dev 48 | 49 | # Production modu için 50 | npm run start 51 | # veya 52 | yarn start 53 | ``` 54 | 55 | ## 🛠️ Komutlar 56 | 57 | ### Admin Komutları 58 | - `/admin_urun_ekle` - Markete ürün eklersiniz 59 | - `/admin_urun_sil` - Marketten ürün silersiniz 60 | - `/admin_para_ver` - Belirttiğiniz kullanıcıya girdiğiniz değer kadar para eklersiniz 61 | - `/admin_para_al` - Belirttiğiniz kullanıdan girdiğiniz değer kadar para alırsınız 62 | 63 | ### Genel Komutlar 64 | - `/yardım` - Komut listesini gösterir 65 | 66 | ## 🔧 Geliştirme 67 | 68 | 1. TypeScript dosyalarını derlemek için: 69 | ```bash 70 | npm run build 71 | # veya 72 | yarn build 73 | ``` 74 | 75 | 2. Linting için: 76 | ```bash 77 | npm run lint 78 | # veya 79 | yarn lint 80 | ``` 81 | 82 | ## 📝 Notlar 83 | 84 | - Bot, Discord.js v14 kullanmaktadır 85 | - Tüm komutlar slash komut olarak tasarlanmıştır 86 | - Hata durumlarında detaylı loglama yapılmaktadır 87 | 88 | ## 🤝 Katkıda Bulunma 89 | 90 | 1. Bu repoyu fork edin 91 | 2. Yeni bir branch oluşturun (`git checkout -b feature/yeniOzellik`) 92 | 3. Değişikliklerinizi commit edin (`git commit -am 'Yeni özellik: XYZ'`) 93 | 4. Branch'inizi push edin (`git push origin feature/yeniOzellik`) 94 | 5. Pull Request oluşturun 95 | 96 | 97 | ## 👨‍💻 Geliştirici 98 | 99 | Developed By Erslly 100 | 101 | --- 102 | 103 | ⭐ Bu projeyi beğendiyseniz yıldız vermeyi unutmayın! 104 | -------------------------------------------------------------------------------- /src/commands/bakiye.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { ChatInputCommandInteraction } from 'discord.js'; 3 | import { Economy } from '../models/economy'; 4 | import { createEmbed, createErrorEmbed } from '../utils/embed'; 5 | 6 | export const data = new SlashCommandBuilder() 7 | .setName('bakiyem') 8 | .setDescription('Bakiyenizi ve ekonomi bilgilerinizi görüntüler') 9 | .addUserOption(option => 10 | option.setName('kullanici') 11 | .setDescription('Bakiyesini görmek istediğiniz kullanıcı') 12 | .setRequired(false)); 13 | 14 | export async function execute(interaction: ChatInputCommandInteraction) { 15 | await interaction.deferReply(); 16 | 17 | const targetUser = interaction.options.getUser('kullanici') ?? interaction.user; 18 | const guildId = interaction.guildId; 19 | 20 | try { 21 | let userEconomy = await Economy.findOne({ userId: targetUser.id, guildId }); 22 | 23 | if (!userEconomy) { 24 | userEconomy = await Economy.create({ 25 | userId: targetUser.id, 26 | guildId, 27 | balance: 0, 28 | bank: 0, 29 | lastDaily: null, 30 | transactions: [] 31 | }); 32 | } 33 | 34 | const formattedBalance = userEconomy.balance.toLocaleString('tr-TR'); 35 | const formattedBank = userEconomy.bank.toLocaleString('tr-TR'); 36 | const totalAssets = userEconomy.balance + userEconomy.bank; 37 | const formattedTotal = totalAssets.toLocaleString('tr-TR'); 38 | 39 | const embed = createEmbed( 40 | `${targetUser.username} Bakiye Bilgileri`, 41 | `### 💰 Cüzdan 42 | **${formattedBalance}** Coin 43 | 44 | ### 🏦 Banka 45 | **${formattedBank}** Coin 46 | 47 | ### 💵 Toplam Varlık 48 | **${formattedTotal}** Coin` 49 | ); 50 | 51 | embed.setDescription(`${embed.data.description}\n\n-# /transfer yatır yazarak bankanıza para yatırabilirsiniz\n` + 52 | `-# /transfer çek diyerek bankanızdan para çekebilirsiniz\n` + 53 | `-# /günlük yazarak günlük ödülünüzü alabilirsiniz`); 54 | 55 | embed.setThumbnail(targetUser.displayAvatarURL()) 56 | .setFooter({ text: `ID: ${targetUser.id} • Son güncelleme: ${new Date().toLocaleTimeString('tr-TR')}` }); 57 | 58 | await interaction.editReply({ embeds: [embed] }); 59 | } catch (error) { 60 | console.error('Bakiye komutu hatası:', error); 61 | await interaction.editReply({ 62 | embeds: [createErrorEmbed('Bakiye bilgisi alınırken bir hata oluştu. Lütfen daha sonra tekrar deneyin.')] 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Client, GatewayIntentBits, Collection, Events, Interaction, REST, Routes, ChatInputCommandInteraction } from 'discord.js'; 2 | import { config } from 'dotenv'; 3 | import path from 'path'; 4 | import fs from 'fs'; 5 | import mongoose from 'mongoose'; 6 | 7 | config(); 8 | 9 | declare module 'discord.js' { 10 | interface Client { 11 | commands: Collection; 12 | } 13 | } 14 | 15 | interface Command { 16 | data: any; 17 | execute: (interaction: ChatInputCommandInteraction) => Promise; 18 | } 19 | 20 | const client = new Client({ 21 | intents: [ 22 | GatewayIntentBits.Guilds, 23 | GatewayIntentBits.GuildMessages, 24 | GatewayIntentBits.MessageContent 25 | ] 26 | }); 27 | 28 | client.commands = new Collection(); 29 | 30 | const commandsPath = path.join(__dirname, 'commands'); 31 | const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.ts') || file.endsWith('.js')); 32 | 33 | const commands: any[] = []; 34 | 35 | for (const file of commandFiles) { 36 | const filePath = path.join(commandsPath, file); 37 | const command = require(filePath); 38 | 39 | if ('data' in command && 'execute' in command) { 40 | client.commands.set(command.data.name, command); 41 | commands.push(command.data.toJSON()); 42 | } else { 43 | console.log(`[UYARI] ${filePath} komutunda "data" veya "execute" eksik.`); 44 | } 45 | } 46 | 47 | mongoose.connect(process.env.MONGODB_URI!) 48 | .then(() => console.log('MongoDB bağlantısı başarılı')) 49 | .catch(err => console.error('MongoDB bağlantı hatası:', err)); 50 | 51 | client.once(Events.ClientReady, async (c) => { 52 | console.log(`Bot ${c.user.tag} olarak giriş yaptı!`); 53 | console.log('Developed By Erslly'); 54 | 55 | c.user.setActivity('Developed By Erslly', { type: 4 }); 56 | 57 | try { 58 | const rest = new REST().setToken(process.env.TOKEN!); 59 | 60 | console.log('Slash komutları kaydediliyor...'); 61 | 62 | await rest.put( 63 | Routes.applicationCommands(c.user.id), 64 | { body: commands } 65 | ); 66 | 67 | console.log('Slash komutları başarıyla kaydedildi!'); 68 | } catch (error) { 69 | console.error('Komutları kaydederken hata oluştu:', error); 70 | } 71 | }); 72 | 73 | client.on(Events.InteractionCreate, async (interaction: Interaction) => { 74 | if (!interaction.isCommand()) return; 75 | 76 | const command = client.commands.get(interaction.commandName); 77 | 78 | if (!command) { 79 | console.error(`${interaction.commandName} komutu bulunamadı.`); 80 | return; 81 | } 82 | 83 | try { 84 | await command.execute(interaction as ChatInputCommandInteraction); 85 | } catch (error) { 86 | console.error(`${interaction.commandName} komutu çalıştırılırken hata:`, error); 87 | 88 | const errorReply = { 89 | content: 'Bu komutu çalıştırırken bir hata oluştu!', 90 | ephemeral: true 91 | }; 92 | 93 | if (interaction.replied || interaction.deferred) { 94 | await interaction.followUp(errorReply); 95 | } else { 96 | await interaction.reply(errorReply); 97 | } 98 | } 99 | }); 100 | 101 | client.login(process.env.TOKEN); 102 | -------------------------------------------------------------------------------- /src/commands/yardım.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { ChatInputCommandInteraction, EmbedBuilder, ColorResolvable } from 'discord.js'; 3 | import { createEmbed, createErrorEmbed } from '../utils/embed'; 4 | 5 | export const data = new SlashCommandBuilder() 6 | .setName('yardım') 7 | .setDescription('Komutlar hakkında bilgi alın'); 8 | 9 | export async function execute(interaction: ChatInputCommandInteraction) { 10 | try { 11 | await interaction.deferReply({ ephemeral: false }); 12 | 13 | const embed = new EmbedBuilder() 14 | .setTitle('Lyra Bot Komutları') 15 | .setDescription('Aşağıda kullanabileceğiniz tüm komutların listesi bulunmaktadır.') 16 | .setColor(0xFF69B4 as ColorResolvable) 17 | .setThumbnail(interaction.client.user?.displayAvatarURL() || null) 18 | .setTimestamp() 19 | .setFooter({ 20 | text: `${interaction.user.username} tarafından istendi`, 21 | iconURL: interaction.user.displayAvatarURL() 22 | }) 23 | .addFields( 24 | { 25 | name: '💰 Ekonomi Komutları', 26 | value: ` 27 | \`/bakiye\` - Bakiyenizi ve ekonomi bilgilerinizi görüntüleyin 28 | \`/günlük\` - Günlük coin ödülünüzü alın 29 | \`/calis\` - Çalışarak coin kazanın 30 | \`/siralama\` - En zengin kullanıcıları görüntüleyin 31 | `, 32 | inline: false 33 | }, 34 | { 35 | name: '🏦 Banka İşlemleri', 36 | value: ` 37 | \`/transfer gönder\` - Başka bir kullanıcıya coin gönderin 38 | \`/transfer yatir\` - Cüzdanınızdan bankaya coin yatırın 39 | \`/transfer çek\` - Bankadan cüzdanınıza coin çekin 40 | `, 41 | inline: false 42 | }, 43 | { 44 | name: '🛍️ Market İşlemleri', 45 | value: ` 46 | \`/market\` - Sunucu marketini görüntüleyin 47 | \`/satin-al\` - Marketten ürün satın alın 48 | \`/envanter\` - Envanterinizi görüntüleyin 49 | `, 50 | inline: false 51 | }, 52 | { 53 | name: '📊 Sıralama Sistemi', 54 | value: ` 55 | \`/siralama cüzdan\` - Cüzdan bakiyesine göre sıralama 56 | \`/siralama banka\` - Banka bakiyesine göre sıralama 57 | \`/siralama toplam\` - Toplam varlığa göre sıralama 58 | `, 59 | inline: false 60 | }, 61 | { 62 | name: '❓ Nasıl Kullanılır?', 63 | value: ` 64 | 1️⃣ \`/calis\` komutu ile coin kazanmaya başlayın (5 dakikada bir kullanabilirsiniz) 65 | 2️⃣ \`/günlük\` komutunu her gün kullanarak bonus coin kazanın 66 | 3️⃣ \`/market\` komutunu kullanarak neler alabileceğinizi görün 67 | 4️⃣ \`/satin-al\` komutu ile istediğiniz ürünü satın alın 68 | 5️⃣ \`/transfer\` komutu ile paranızı güvende tutun veya arkadaşlarınızla paylaşın 69 | 6️⃣ \`/siralama\` komutu ile en zenginler arasında yerinizi görün 70 | `, 71 | inline: false 72 | }, 73 | { 74 | name: '🔗 Yararlı Bağlantılar', 75 | value: ` 76 | • [Geliştirici](https://erslly.xyz/) 77 | • [GitHub](https://github.com/erslly) 78 | `, 79 | inline: false 80 | } 81 | ); 82 | 83 | await interaction.editReply({ embeds: [embed] }); 84 | } catch (error) { 85 | console.error('Yardım komutu hatası:', error); 86 | await interaction.editReply({ 87 | embeds: [createErrorEmbed('Yardım menüsü gösterilirken bir hata oluştu.')] 88 | }); 89 | } 90 | } -------------------------------------------------------------------------------- /src/commands/satin-al.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { CommandInteraction, GuildMember } from 'discord.js'; 3 | import { Economy } from '../models/economy'; 4 | import { ShopItem } from '../models/shop'; 5 | import { Inventory } from '../models/inventory'; 6 | import { createEmbed, createErrorEmbed, createSuccessEmbed } from '../utils/embed'; 7 | import { Types } from 'mongoose'; 8 | 9 | export const data = new SlashCommandBuilder() 10 | .setName('satin-al') 11 | .setDescription('Marketten ürün satın alın') 12 | .addStringOption(option => 13 | option.setName('urun') 14 | .setDescription('Satın almak istediğiniz ürünün adı') 15 | .setRequired(true)); 16 | 17 | export async function execute(interaction: CommandInteraction) { 18 | await interaction.deferReply(); 19 | 20 | const userId = interaction.user.id; 21 | const guildId = interaction.guildId; 22 | const itemName = interaction.options.get('urun')?.value as string; 23 | 24 | try { 25 | const item = await ShopItem.findOne({ 26 | guildId, 27 | name: { $regex: new RegExp(`^${itemName}$`, 'i') } 28 | }); 29 | 30 | if(!item) { 31 | return interaction.editReply({ 32 | embeds: [createErrorEmbed(`"${itemName}" adında bir ürün bulunamadı.`)] 33 | }); 34 | } 35 | 36 | const stock = item.stock ?? -1; 37 | if (stock !== -1 && stock <= 0) { 38 | return interaction.editReply({ 39 | embeds: [createErrorEmbed(`"${itemName}" ürünü stokta bulunmadığından satın alamadınız.`)] 40 | }); 41 | } 42 | 43 | const userEconomy = await Economy.findOne({ userId, guildId }); 44 | 45 | if(!userEconomy || userEconomy.balance < item.price) { 46 | return interaction.editReply({ 47 | embeds: [createErrorEmbed(`Bu ürünü satın almak için yeterli coininiz yok. Gereken: ${item.price} coin, Mevcut: ${userEconomy?.balance || 0} coin`)] 48 | }); 49 | } 50 | 51 | let inventory = await Inventory.findOne({ userId, guildId }); 52 | 53 | if (!inventory) { 54 | inventory = await Inventory.create({ userId, guildId, items: [] }); 55 | } 56 | 57 | const existingItem = inventory.items.find(invItem => 58 | invItem.itemId.toString() === (item._id as Types.ObjectId).toString()); 59 | 60 | if (existingItem) { 61 | existingItem.quantity += 1; 62 | existingItem.purchasedAt = new Date(); 63 | } else { 64 | inventory.items.push({ 65 | itemId: item._id as Types.ObjectId, 66 | quantity: 1, 67 | purchasedAt: new Date() 68 | }); 69 | } 70 | 71 | if (item.role) { 72 | const member = interaction.member; 73 | if (member instanceof GuildMember && !member.roles.cache.has(item.role)) { 74 | try { 75 | await member.roles.add(item.role); 76 | } catch (err) { 77 | console.error('Rol verme hatası:', err); 78 | return interaction.editReply({ 79 | embeds: [createErrorEmbed('Rol verilirken bir hata oluştu. Lütfen yetkililerle iletişime geçin.')] 80 | }); 81 | } 82 | } 83 | } 84 | 85 | if (stock > 0) { 86 | item.stock = stock - 1; 87 | await item.save(); 88 | } 89 | 90 | userEconomy.balance -= item.price; 91 | await userEconomy.save(); 92 | await inventory.save(); 93 | 94 | const embed = createSuccessEmbed( 95 | `"${item.name}" ürününü ${item.price.toLocaleString('tr-TR')} coin karşılığında satın aldınız!\n\nYeni bakiyeniz: **${userEconomy.balance.toLocaleString('tr-TR')}** coin` 96 | ); 97 | 98 | await interaction.editReply({ embeds: [embed] }) 99 | } catch (error) { 100 | console.error('Satın alma komutu hatası:', error); 101 | await interaction.editReply({ 102 | embeds: [createErrorEmbed('Satın alma işlemi sırasında bir hata oluştu. Lütfen daha sonra tekrar deneyin.')] 103 | }); 104 | } 105 | } -------------------------------------------------------------------------------- /src/commands/calis.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { CommandInteraction, ColorResolvable } from 'discord.js'; 3 | import { Economy } from '../models/economy'; 4 | import { createEmbed, createErrorEmbed } from '../utils/embed'; 5 | 6 | const MIN_WORK_AMOUNT = 50; 7 | const MAX_WORK_AMOUNT = 200; 8 | const COOLDOWN = 5 * 60 * 1000; 9 | const MAX_WORK_PER_DAY = 5; 10 | const WORK_COLOR: ColorResolvable = '#FFD700'; 11 | 12 | const WORK_MESSAGES = [ 13 | "Bir web sitesi tasarladınız ve {amount} coin kazandınız.", 14 | "Bir dükkanda part-time çalıştınız ve {amount} coin kazandınız.", 15 | "Bahçe düzenlemesi yaptınız ve {amount} coin kazandınız.", 16 | "Birinin evcil hayvanına baktınız ve {amount} coin kazandınız.", 17 | "Bir yazılım bug'ını düzelttiniz ve {amount} coin kazandınız.", 18 | "Online bir anket doldurdunuz ve {amount} coin kazandınız.", 19 | "Komşunuzun çimleri biçtiniz ve {amount} coin kazandınız.", 20 | "Hasta bir arkadaşınıza yardım ettiniz ve {amount} coin kazandınız." 21 | ]; 22 | 23 | export const data = new SlashCommandBuilder() 24 | .setName('çalış') 25 | .setDescription('Çalışarak para kazanın'); 26 | 27 | export async function execute(interaction: CommandInteraction) { 28 | await interaction.deferReply(); 29 | 30 | const userId = interaction.user.id; 31 | const guildId = interaction.guildId; 32 | const username = interaction.user.username; 33 | const now = new Date(); 34 | const formattedTime = `${now.toLocaleDateString('tr-TR')} ${now.toLocaleTimeString('tr-TR')}`; 35 | 36 | try { 37 | let userEconomy = await Economy.findOne({ userId, guildId }); 38 | 39 | if (!userEconomy) { 40 | userEconomy = await Economy.create({ 41 | userId, 42 | guildId, 43 | balance: 0, 44 | bank: 0, 45 | lastWork: new Date(0), 46 | workCount: 0 47 | }); 48 | } 49 | 50 | const lastWork = new Date(userEconomy.lastWork); 51 | const timeDiff = now.getTime() - lastWork.getTime(); 52 | 53 | if (timeDiff >= 24 * 60 * 60 * 1000) { 54 | userEconomy.workCount = 0; 55 | } 56 | 57 | if (userEconomy.workCount >= MAX_WORK_PER_DAY) { 58 | return interaction.editReply({ 59 | embeds: [createErrorEmbed(`**${username}**, bugün için çalışma limitinize ulaştınız! Yarın tekrar çalışabilirsiniz.`) 60 | .setFooter({ text: `${formattedTime} • Limit` }) 61 | ] 62 | }); 63 | } 64 | 65 | if (timeDiff < COOLDOWN) { 66 | const remainingTime = COOLDOWN - timeDiff; 67 | const nextAvailableTime = Date.now() + remainingTime; 68 | 69 | return interaction.editReply({ 70 | embeds: [createErrorEmbed(`**${username}**, çok yorgunsun! sonra tekrar çalışabilirsin.`) 71 | .setFooter({ text: `${formattedTime} • Cooldown` }) 72 | ] 73 | }); 74 | } 75 | 76 | const amount = Math.floor(Math.random() * (MAX_WORK_AMOUNT - MIN_WORK_AMOUNT + 1)) + MIN_WORK_AMOUNT; 77 | 78 | const messageIndex = Math.floor(Math.random() * WORK_MESSAGES.length); 79 | const workMessage = WORK_MESSAGES[messageIndex].replace('{amount}', `**${amount}**`); 80 | 81 | userEconomy.balance += amount; 82 | userEconomy.lastWork = now; 83 | userEconomy.workCount += 1; 84 | await userEconomy.save(); 85 | 86 | const nextWorkTime = new Date(now.getTime() + COOLDOWN); 87 | const nextWorkTimestamp = Math.floor(nextWorkTime.getTime() / 1000); 88 | 89 | const embed = createEmbed( 90 | 'Çalışma Sonucu', 91 | `${workMessage}\n\n**Bakiye Bilgisi:**\n• Yeni bakiyeniz: **${userEconomy.balance.toLocaleString('tr-TR')}** coin\n• Kazanç: **+${amount.toLocaleString('tr-TR')}** coin\n• Banka: **${userEconomy.bank.toLocaleString('tr-TR')}** coin\n\nSonraki çalışma: ` 92 | ) 93 | .setColor(WORK_COLOR) 94 | .setThumbnail(interaction.user.displayAvatarURL({ size: 256 })) 95 | .setTimestamp(now) 96 | .setFooter({ 97 | text: username, 98 | iconURL: interaction.user.displayAvatarURL() 99 | }); 100 | 101 | await interaction.editReply({ embeds: [embed] }); 102 | } catch (error) { 103 | console.error('Çalışma komutu hatası:', error); 104 | await interaction.editReply({ 105 | embeds: [createErrorEmbed('Çalışma yapılırken bir hata oluştu.') 106 | .setFooter({ text: `${formattedTime} • Hata` }) 107 | ] 108 | }); 109 | } 110 | } -------------------------------------------------------------------------------- /src/commands/transfer.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { ChatInputCommandInteraction } from 'discord.js'; 3 | import { Economy } from '../models/economy'; 4 | import { createEmbed, createErrorEmbed, createSuccessEmbed } from '../utils/embed'; 5 | 6 | export const data = new SlashCommandBuilder() 7 | .setName('transfer') 8 | .setDescription('Para transferi yapın') 9 | .addSubcommand(subcommand => 10 | subcommand 11 | .setName('gönder') 12 | .setDescription('Diğer bir kullanıcıya para gönderin') 13 | .addUserOption(option => 14 | option.setName('kullanıcı') 15 | .setDescription('Para göndermek istediğiniz kullanıcı') 16 | .setRequired(true)) 17 | .addIntegerOption(option => 18 | option.setName('miktar') 19 | .setDescription('Göndermek istediğiniz miktar') 20 | .setRequired(true))) 21 | .addSubcommand(subcommand => 22 | subcommand 23 | .setName('yatir') 24 | .setDescription('Cüzdanınızdan bankaya para yatırın') 25 | .addIntegerOption(option => 26 | option.setName('miktar') 27 | .setDescription('Yatırmak istediğiniz miktar') 28 | .setRequired(true))) 29 | .addSubcommand(subcommand => 30 | subcommand 31 | .setName('çek') 32 | .setDescription('Bankadan cüzdanınıza para çekin') 33 | .addIntegerOption(option => 34 | option.setName('miktar') 35 | .setDescription('Çekmek istediğiniz miktar') 36 | .setRequired(true))); 37 | 38 | export async function execute(interaction: ChatInputCommandInteraction) { 39 | try { 40 | await interaction.deferReply({ ephemeral: false }); 41 | 42 | const userId = interaction.user.id; 43 | const guildId = interaction.guildId; 44 | const subcommand = interaction.options.getSubcommand(); 45 | const amount = interaction.options.getInteger('miktar'); 46 | 47 | if (!amount || amount <= 0) { 48 | return interaction.editReply({ 49 | embeds: [createErrorEmbed('Geçersiz miktar. Pozitif bir sayı girmelisiniz.')] 50 | }); 51 | } 52 | 53 | let userEconomy = await Economy.findOne({ userId, guildId }); 54 | 55 | if(!userEconomy) { 56 | userEconomy = await Economy.create({ 57 | userId, 58 | guildId, 59 | balance: 0, 60 | bank: 0 61 | }); 62 | } 63 | 64 | if (subcommand === 'gönder') { 65 | const targetUser = interaction.options.getUser('kullanıcı'); 66 | 67 | if (!targetUser) { 68 | return interaction.editReply({ 69 | embeds: [createErrorEmbed('Geçersiz kullanıcı.')] 70 | }); 71 | } 72 | 73 | if (targetUser.id === userId) { 74 | return interaction.editReply({ 75 | embeds: [createErrorEmbed('Kendinize para gönderemezsiniz.')] 76 | }); 77 | } 78 | 79 | if (userEconomy.balance < amount) { 80 | return interaction.editReply({ 81 | embeds: [createErrorEmbed(`Yeterli bakiyeniz yok. Mevcut bakiyeniz: ${userEconomy.balance.toLocaleString('tr-TR')} coin`)] 82 | }); 83 | } 84 | 85 | let targetEconomy = await Economy.findOne({ userId: targetUser.id, guildId }); 86 | 87 | if (!targetEconomy) { 88 | targetEconomy = await Economy.create({ 89 | userId: targetUser.id, 90 | guildId, 91 | balance: 0, 92 | bank: 0 93 | }); 94 | } 95 | 96 | userEconomy.balance -= amount; 97 | targetEconomy.balance += amount; 98 | 99 | await userEconomy.save(); 100 | await targetEconomy.save(); 101 | 102 | return interaction.editReply({ 103 | embeds: [createSuccessEmbed(`Başarıyla ${targetUser.username} adlı kullanıcıya ${amount.toLocaleString('tr-TR')} coin gönderdiniz.\n\nMevcut bakiyeniz: ${userEconomy.balance.toLocaleString('tr-TR')} coin`)] 104 | }); 105 | } 106 | 107 | else if (subcommand === 'yatir') { 108 | if (userEconomy.balance < amount) { 109 | return interaction.editReply({ 110 | embeds: [createErrorEmbed(`Yeterli bakiyeniz yok. Mevcut bakiyeniz: ${userEconomy.balance.toLocaleString('tr-TR')} coin`)] 111 | }); 112 | } 113 | 114 | userEconomy.balance -= amount; 115 | userEconomy.bank += amount; 116 | 117 | await userEconomy.save(); 118 | 119 | return interaction.editReply({ 120 | embeds: [createSuccessEmbed(`${amount.toLocaleString('tr-TR')} coin bankaya yatırıldı!\n\nCüzdan: ${userEconomy.balance.toLocaleString('tr-TR')} coin\nBanka: ${userEconomy.bank.toLocaleString('tr-TR')} coin`)] 121 | }); 122 | } 123 | 124 | else if (subcommand === 'çek') { 125 | if (userEconomy.bank < amount) { 126 | return interaction.editReply({ 127 | embeds: [createErrorEmbed(`Bankada yeterli bakiyeniz yok. Banka bakiyeniz: ${userEconomy.bank.toLocaleString('tr-TR')} coin`)] 128 | }); 129 | } 130 | 131 | userEconomy.bank -= amount; 132 | userEconomy.balance += amount; 133 | 134 | await userEconomy.save(); 135 | 136 | return interaction.editReply({ 137 | embeds: [createSuccessEmbed(`${amount.toLocaleString('tr-TR')} coin bankadan çekildi!\n\nCüzdan: ${userEconomy.balance.toLocaleString('tr-TR')} coin\nBanka: ${userEconomy.bank.toLocaleString('tr-TR')} coin`)] 138 | }); 139 | } else { 140 | return interaction.editReply({ 141 | embeds: [createErrorEmbed('Geçersiz alt komut.')] 142 | }); 143 | } 144 | } catch (error) { 145 | console.error('Transfer komutu hatası:', error); 146 | try { 147 | await interaction.editReply({ 148 | embeds: [createErrorEmbed('Para transferi sırasında bir hata oluştu. Lütfen daha sonra tekrar deneyin.')] 149 | }); 150 | } catch (e) { 151 | console.error('Hata mesajı gönderilemedi:', e); 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /src/commands/siralama.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { ChatInputCommandInteraction, EmbedBuilder, ColorResolvable } from 'discord.js'; 3 | import { Economy } from '../models/economy'; 4 | import { createErrorEmbed } from '../utils/embed'; 5 | 6 | export const data = new SlashCommandBuilder() 7 | .setName('siralama') 8 | .setDescription("En çok coine'e sahip olan kullanıcıları gösterir") 9 | .addStringOption(option => 10 | option.setName('tür') 11 | .setDescription("Sıralama türünü belirtin") 12 | .setRequired(true) 13 | .addChoices( 14 | { name: 'Cüzdan', value: 'balance' }, 15 | { name: 'Banka', value: 'bank' }, 16 | { name: 'Toplam', value: 'total' } 17 | )); 18 | 19 | export async function execute(interaction: ChatInputCommandInteraction) { 20 | await interaction.deferReply(); 21 | 22 | const guildId = interaction.guildId; 23 | const type = interaction.options.getString('tür'); 24 | const guild = interaction.guild; 25 | 26 | try { 27 | let sortField = {}; 28 | let title = ''; 29 | let emoji = ''; 30 | let color: ColorResolvable = '#0099ff'; 31 | 32 | if (type === 'balance') { 33 | sortField = { balance: -1 }; 34 | title = 'Cüzdan Sıralaması'; 35 | emoji = '💰'; 36 | color = 0xFFD700; 37 | } else if (type === 'bank') { 38 | sortField = { bank: -1 }; 39 | title = 'Banka Sıralaması'; 40 | emoji = '🏦'; 41 | color = 0x4169E1; 42 | } else { 43 | title = 'Toplam Varlık Sıralaması'; 44 | emoji = '💵'; 45 | color = 0x32CD32; 46 | } 47 | 48 | const allEconomies = await Economy.find({ guildId }).sort(sortField).limit(10); 49 | 50 | if (allEconomies.length === 0) { 51 | const emptyEmbed = new EmbedBuilder() 52 | .setTitle(`${emoji} ${title}`) 53 | .setDescription('Hiç veri bulunamadı. İlk sen ol!') 54 | .setColor(color) 55 | .setFooter({ text: `${guild?.name || 'Sunucu'} Ekonomi Sistemi` }) 56 | .setTimestamp(); 57 | return interaction.editReply({ embeds: [emptyEmbed] }); 58 | } 59 | 60 | if (type === 'total') { 61 | allEconomies.sort((a, b) => (b.balance + b.bank) - (a.balance + a.bank)); 62 | } 63 | 64 | const embed = new EmbedBuilder() 65 | .setTitle(`${emoji} ${title}`) 66 | .setDescription(`**${guild?.name || 'Sunucu'}** ekonomi sisteminde en zengin 10 kişi`) 67 | .setColor(color) 68 | .setThumbnail(guild?.iconURL() || null) 69 | .setFooter({ 70 | text: `${interaction.user.username} tarafından istendi • ${new Date().toLocaleDateString('tr-TR')}`, 71 | iconURL: interaction.user.displayAvatarURL() 72 | }) 73 | .setTimestamp(); 74 | 75 | const medals = ['🥇', '🥈', '🥉']; 76 | let leaderboardText = ''; 77 | 78 | for (let i = 0; i < allEconomies.length; i++) { 79 | const economy = allEconomies[i]; 80 | const user = await interaction.client.users.fetch(economy.userId).catch(() => null); 81 | const username = user ? user.username : 'Bilinmeyen Kullanıcı'; 82 | const rank = i < 3 ? medals[i] : `${i + 1}.`; 83 | 84 | let value; 85 | if (type === 'balance') { 86 | value = economy.balance; 87 | } else if (type === 'bank') { 88 | value = economy.bank; 89 | } else { 90 | value = economy.balance + economy.bank; 91 | } 92 | 93 | leaderboardText += `**${rank} ${username}**\n`; 94 | leaderboardText += `┗ ${emoji} **${value.toLocaleString('tr-TR')}** coin\n\n`; 95 | } 96 | 97 | embed.setDescription(`**${guild?.name || 'Sunucu'}** ekonomi sisteminde en zengin 10 kişi\n\n${leaderboardText.trim()}`); 98 | 99 | const requestingUser = allEconomies.find(e => e.userId === interaction.user.id); 100 | if (requestingUser) { 101 | let userRank = 0; 102 | let totalUsers = 0; 103 | 104 | if (type === 'balance') { 105 | const allUsers = await Economy.countDocuments({ guildId, balance: { $gt: 0 } }); 106 | const betterUsers = await Economy.countDocuments({ 107 | guildId, 108 | balance: { $gt: requestingUser.balance } 109 | }); 110 | userRank = betterUsers + 1; 111 | totalUsers = allUsers; 112 | } else if (type === 'bank') { 113 | const allUsers = await Economy.countDocuments({ guildId, bank: { $gt: 0 } }); 114 | const betterUsers = await Economy.countDocuments({ 115 | guildId, 116 | bank: { $gt: requestingUser.bank } 117 | }); 118 | userRank = betterUsers + 1; 119 | totalUsers = allUsers; 120 | } else { 121 | const allUsers = await Economy.countDocuments({ 122 | guildId, 123 | $or: [{ balance: { $gt: 0 } }, { bank: { $gt: 0 } }] 124 | }); 125 | 126 | const total = requestingUser.balance + requestingUser.bank; 127 | const betterUsers = await Economy.countDocuments({ 128 | guildId, 129 | $expr: { $gt: [{ $add: ["$balance", "$bank"] }, total] } 130 | }); 131 | userRank = betterUsers + 1; 132 | totalUsers = allUsers; 133 | } 134 | 135 | let userValue; 136 | if (type === 'balance') { 137 | userValue = requestingUser.balance; 138 | } else if (type === 'bank') { 139 | userValue = requestingUser.bank; 140 | } else { 141 | userValue = requestingUser.balance + requestingUser.bank; 142 | } 143 | 144 | embed.addFields({ 145 | name: '🔍 Senin Sıralaman', 146 | value: `**${userRank}./${totalUsers}** sıradasın\n${emoji} **${userValue.toLocaleString('tr-TR')}** coin`, 147 | inline: false 148 | }); 149 | } 150 | 151 | await interaction.editReply({ embeds: [embed] }); 152 | } catch (error) { 153 | console.error('Sıralama komutu hatası:', error); 154 | await interaction.editReply({ embeds: [createErrorEmbed('Sıralama bilgileri alınırken bir hata oluştu.')] }); 155 | } 156 | } -------------------------------------------------------------------------------- /src/commands/admin.ts: -------------------------------------------------------------------------------- 1 | import { SlashCommandBuilder } from '@discordjs/builders'; 2 | import { ChatInputCommandInteraction, CommandInteraction } from 'discord.js'; 3 | import { Economy } from '../models/economy'; 4 | import { ShopItem } from '../models/shop'; 5 | import { createEmbed, createErrorEmbed, createSuccessEmbed } from '../utils/embed'; 6 | 7 | const ADMIN_IDS = process.env.ADMIN_IDS ? process.env.ADMIN_IDS.split(',') : []; 8 | 9 | export const data = new SlashCommandBuilder() 10 | .setName('admin') 11 | .setDescription('Admin komutları') 12 | .addSubcommand(subcommand => 13 | subcommand 14 | .setName('para_ver') 15 | .setDescription('Kullanıcıya para ver') 16 | .addUserOption(option => option.setName('kullanici').setDescription('Para vermek istediğiniz kullanıcı').setRequired(true)) 17 | .addIntegerOption(option => option.setName('miktar').setDescription('Vermek istediğiniz miktar').setRequired(true))) 18 | .addSubcommand(subcommand => 19 | subcommand 20 | .setName('para_al') 21 | .setDescription('Kullanıcıdan para al') 22 | .addUserOption(option => option.setName('kullanici').setDescription('Para almak istediğiniz kullanıcı').setRequired(true)) 23 | .addIntegerOption(option => option.setName('miktar').setDescription('Almak istediğiniz miktar').setRequired(true))) 24 | .addSubcommand(subcommand => 25 | subcommand 26 | .setName('urun_ekle') 27 | .setDescription('Markete ürün ekle') 28 | .addStringOption(option => option.setName('isim').setDescription('Ürün ismi').setRequired(true)) 29 | .addStringOption(option => option.setName('aciklama').setDescription('Ürün açıklaması').setRequired(true)) 30 | .addIntegerOption(option => option.setName('fiyat').setDescription('Ürün fiyatı').setRequired(true)) 31 | .addRoleOption(option => option.setName('rol').setDescription('Ürünle verilecek rol').setRequired(false)) 32 | .addIntegerOption(option => option.setName('stok').setDescription('Ürün stok adedi (-1 = sınırsız)').setRequired(false))) 33 | .addSubcommand(subcommand => 34 | subcommand 35 | .setName('urun_sil') 36 | .setDescription('Marketten ürün sil') 37 | .addStringOption(option => option.setName('isim').setDescription('Silinecek ürünün ismi').setRequired(true))); 38 | 39 | export async function execute(interaction: ChatInputCommandInteraction) { 40 | await interaction.deferReply({ ephemeral: true }); 41 | 42 | const userId = interaction.user.id; 43 | 44 | if (!ADMIN_IDS.includes(userId)) { 45 | return interaction.editReply({ 46 | embeds: [createErrorEmbed('Bu komutu kullanmak için yetkiniz yok.')] 47 | }); 48 | } 49 | 50 | const guildId = interaction.guildId; 51 | const subcommand = interaction.options.getSubcommand(); 52 | 53 | try { 54 | if (subcommand === 'para_ver') { 55 | const targetUser = interaction.options.getUser('kullanici'); 56 | const amount = interaction.options.getInteger('miktar'); 57 | 58 | if (!targetUser || !amount || amount <= 0) { 59 | return interaction.editReply({ 60 | embeds: [createErrorEmbed('Geçersiz kullanıcı veya miktar. Pozitif bir sayı girmelisiniz.')] 61 | }); 62 | } 63 | 64 | let targetEconomy = await Economy.findOne({ userId: targetUser.id, guildId }); 65 | 66 | if (!targetEconomy) { 67 | targetEconomy = await Economy.create({ 68 | userId: targetUser.id, 69 | guildId, 70 | balance: 0, 71 | bank: 0 72 | }); 73 | } 74 | 75 | targetEconomy.balance += amount; 76 | await targetEconomy.save(); 77 | 78 | return interaction.editReply({ 79 | embeds: [createSuccessEmbed(`${targetUser.username} kullanıcısına ${amount.toLocaleString('tr-TR')} coin verildi!\n\nYeni bakiyesi: ${targetEconomy.balance.toLocaleString('tr-TR')} coin`)] 80 | }); 81 | } 82 | else if (subcommand === 'para_al') { 83 | const targetUser = interaction.options.getUser('kullanici'); 84 | const amount = interaction.options.getInteger('miktar'); 85 | 86 | if (!targetUser || !amount || amount <= 0) { 87 | return interaction.editReply({ 88 | embeds: [createErrorEmbed('Geçersiz kullanıcı veya miktar. Pozitif bir sayı girmelisiniz.')] 89 | }); 90 | } 91 | 92 | let targetEconomy = await Economy.findOne({ userId: targetUser.id, guildId }); 93 | 94 | if (!targetEconomy) { 95 | return interaction.editReply({ 96 | embeds: [createErrorEmbed(`${targetUser.username} kullanıcısının henüz ekonomi verileri bulunmuyor.`)] 97 | }); 98 | } 99 | 100 | if (targetEconomy.balance < amount) { 101 | return interaction.editReply({ 102 | embeds: [createErrorEmbed(`${targetUser.username} kullanıcısının yeterli bakiyesi yok. Mevcut bakiyesi: ${targetEconomy.balance.toLocaleString('tr-TR')} coin`)] 103 | }); 104 | } 105 | 106 | targetEconomy.balance -= amount; 107 | await targetEconomy.save(); 108 | 109 | return interaction.editReply({ 110 | embeds: [createSuccessEmbed(`${targetUser.username} kullanıcısından ${amount.toLocaleString('tr-TR')} coin alındı!\n\nYeni bakiyesi: ${targetEconomy.balance.toLocaleString('tr-TR')} coin`)] 111 | }); 112 | } 113 | else if (subcommand === 'urun_ekle') { 114 | const name = interaction.options.getString('isim'); 115 | const description = interaction.options.getString('aciklama'); 116 | const price = interaction.options.getInteger('fiyat'); 117 | const role = interaction.options.getRole('rol')?.id; 118 | const stock = interaction.options.getInteger('stok') ?? -1; 119 | 120 | if (!name || !description || !price || price <= 0) { 121 | return interaction.editReply({ 122 | embeds: [createErrorEmbed('Geçersiz ürün bilgileri. Lütfen tüm alanları doğru doldurun.')] 123 | }); 124 | } 125 | 126 | const existingItem = await ShopItem.findOne({ 127 | guildId, 128 | name: { $regex: new RegExp(`^${name}$`, 'i') } 129 | }); 130 | 131 | if (existingItem) { 132 | return interaction.editReply({ 133 | embeds: [createErrorEmbed(`"${name}" adında bir ürün zaten mevcut.`)] 134 | }); 135 | } 136 | 137 | const newItem = await ShopItem.create({ 138 | guildId, 139 | name, 140 | description, 141 | price, 142 | role, 143 | stock 144 | }); 145 | 146 | return interaction.editReply({ 147 | embeds: [createSuccessEmbed(`"${name}" adlı ürün ${price.toLocaleString('tr-TR')} coin fiyatla markete eklendi!`)] 148 | }); 149 | } 150 | else if (subcommand === 'urun_sil') { 151 | const name = interaction.options.getString('isim'); 152 | 153 | if (!name) { 154 | return interaction.editReply({ 155 | embeds: [createErrorEmbed('Geçersiz ürün ismi.')] 156 | }); 157 | } 158 | 159 | const item = await ShopItem.findOne({ 160 | guildId, 161 | name: { $regex: new RegExp(`^${name}$`, 'i') } 162 | }); 163 | 164 | if (!item) { 165 | return interaction.editReply({ 166 | embeds: [createErrorEmbed(`"${name}" adında bir ürün bulunamadı.`)] 167 | }); 168 | } 169 | 170 | await item.deleteOne(); 171 | 172 | return interaction.editReply({ 173 | embeds: [createSuccessEmbed(`"${item.name}" adlı ürün marketten silindi!`)] 174 | }); 175 | } 176 | } catch (error) { 177 | console.error('Admin komutu hatası:', error); 178 | await interaction.editReply({ embeds: [createErrorEmbed('Komut işlenirken bir hata oluştu.')] }); 179 | } 180 | } --------------------------------------------------------------------------------