質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1653閲覧

discord.pyのbotのレベル機能について

Milestone

総合スコア3

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/06/30 13:50

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
pythonでレベル上げ機能を搭載したbotを作り、dillモジュールを使ってすべてのメンバーのレベル保存しています。

発生している問題・エラーメッセージ

botを再起動する時にレベルを確認してみると、レベル・XPが少し前の状態に戻っていました。

該当のソースコード

python

1import discord 2from discord.ext import tasks, commands 3import datetime as dt 4import dill 5from random import randint 6 7intents = discord.Intents.all() 8class mycog(commands.Cog): 9 def __init__(self, client): 10 self.needxp = [int(2500 * ((x+1) ** (1/3))) for x in range(0, 100)] 11 self.lastmsg = {} 12 self.level = {} 13 self.loop.start() 14 15 16 17 try: 18 with open('level.dill', 'rb') as f: 19 self.level = dill.load(f) 20 except: 21 pass 22 23 24 try: 25 with open('xpratio.dill', 'rb') as f: 26 self.xpratio = dill.load(f) 27 28 except: 29 pass 30 31 32 @commands.Cog.listener() 33 async def on_ready(self): 34 print('BOTが起動しました') 35 36 @commands.Cog.listener() 37 async def on_message(self, message): 38 if message.author.bot: return 39 guild = message.guild 40 member = guild.get_member(message.author.id) 41 #10秒以内にメッセージを送信していないか確認してスパム判定 42 try: 43 if dt.datetime.now() - dt.timedelta(seconds=5) < self.lastmsg[member.id]: 44 self.lastmsg[member.id] = dt.datetime.now() 45 return 46 else: 47 self.lastmsg[member.id] = dt.datetime.now() 48 except: 49 self.lastmsg[member.id] = dt.datetime.now() 50 51 if randint(0, 3) > 0: 52 self.level[guild.id][member.id]['xp'] += randint(100, 120) 53 if self.level[guild.id][member.id]['xp'] >= self.needxp[self.level[guild.id][member.id]['level']]: 54 self.level[guild.id][member.id]['xp'] -= self.needxp[self.level[guild.id][member.id]['level']] 55 self.level[guild.id][member.id]['level'] += 1 56 await message.channel.send(f'{member.mention}のレベルが{self.level[guild.id][member.id]["level"]}になりました!') 57 if self.level[guild.id][member.id]['level'] in self.reward[guild.id].keys(): 58 role = guild.get_role(self.reward[guild.id][self.level[guild.id][member.id]['level']]) 59 member.add_roles(role) 60 print(f'{message.author}のがレベル{self.level[guild.id][member.id]["level"]}、XP{self.level[guild.id][member.id]["xp"]} / {self.needxp[self.level[guild.id][member.id]["level"]]}になりました') 61 62 with open('level.dill', 'wb') as f: 63 dill.dump(self.level, f) 64 65 66 @commands.command() 67 @commands.has_permissions(administrator=True) 68 async def reward(self, ctx, level, role_id): 69 #レベル報酬を設定 70 guild = ctx.guild 71 print(role_id) 72 role = guild.get_role(int(role_id[3:-1])) 73 try: 74 self.reward[guild.id][level] = role.id 75 except KeyError: 76 self.reward[guild.id] = {} 77 self.reward[guild.id][level] = role.id 78 with open('reward.dill', 'wb') as f: 79 dill.dump(self.reward, f) 80 81 @tasks.loop(seconds=10) 82 async def loop(self): 83 for guild in client.guilds: 84 if guild.id not in self.level.keys(): 85 self.level[guild.id] = {} 86 for member in guild.members: 87 if member.id not in self.level[guild.id].keys(): 88 self.level[guild.id][member.id] = {'level': 0, 'xp': 0} 89 if member.id not in self.dict[guild.id].keys(): 90 self.dict[guild.id][member.id] = 0 91 with open('level.dill', 'wb') as f: 92 dill.dump(self.level, f) 93 94 @commands.command() 95 async def level(self, ctx): 96 #レベル確認コマンド 97 channel = ctx.channel 98 guild = ctx.guild 99 member = guild.get_member(ctx.author.id) 100 embed = discord.Embed(title=f'{ctx.author}のレベル', description='''レベル: {0} 101XP: {1} / {2}'''.format(self.level[guild.id][member.id]['level'], self.level[guild.id][member.id]['xp'], self.needxp[self.level[guild.id][member.id]['level']])) 102 await channel.send(embed=embed) 103 104 105 106client = commands.Bot(command_prefix="!", intents=intents) 107client.add_cog(mycog(client)) 108 109 110TOKEN = "(トークン)" 111client.run(TOKEN)

試したこと

試せることがありませんでした。すみません。

補足情報(FW/ツールのバージョンなど)

python 3.7.4

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

udon-ken

2021/07/01 12:23

そのモジュールを使った事がありませんし、長いコードを読む気にもなりませんが、何点か確認すべき点があると思います。 ・これまではbotを再起動してもレベル等は確実に保持されていたのでしょうか? ・今回再起動すると少し前の状態に戻っていたという事ですが、戻った事に間違いないでしょうか? 例:「あの人は昨日レベル10だった。それから動きがあったから確実に11以上であるはず。なのに今日も10だから戻った」などというのは確実に戻ったとは言えません。なぜなら、カウントがおかしくてそもそも11になってない可能性もありますので。 ・レベルが戻ったとして、今回気付いた以降はどうなのでしょうか?それ以降も戻るのでしょうか?それ以降は問題ないのでしょうか?
guest

回答1

0

自己解決

後日原因を調べてみたところ、dillモジュールを使って保存すると、質問した内容と同様の不具合が発生することがあるようです。何故そのような不具合が発生するかはわかりませんが、保存する時に使うモジュールをpickleモジュールに変更したところ、前のような不具合は発生しなくなりました。

投稿2021/07/01 12:34

Milestone

総合スコア3

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問