From 79aa0eb87d4474fef0efed27a84247ee019c9e02 Mon Sep 17 00:00:00 2001 From: seth Date: Tue, 15 Jun 2021 05:34:48 -0500 Subject: [PATCH] Refactor discord webhook code into new module --- bemani/backend/iidx/cannonballers.py | 78 +++++++++++---------------- bemani/backend/iidx/copula.py | 79 ++++++++++++---------------- bemani/backend/iidx/pendual.py | 79 ++++++++++++---------------- bemani/backend/iidx/rootage.py | 78 +++++++++++---------------- bemani/backend/iidx/sinobuz.py | 79 ++++++++++++---------------- bemani/backend/iidx/spada.py | 79 ++++++++++++---------------- bemani/data/__init__.py | 2 + bemani/data/data.py | 2 + bemani/data/triggers.py | 37 +++++++++++++ config/server.yaml | 6 ++- 10 files changed, 241 insertions(+), 278 deletions(-) create mode 100644 bemani/data/triggers.py diff --git a/bemani/backend/iidx/cannonballers.py b/bemani/backend/iidx/cannonballers.py index f531626..1e73b97 100644 --- a/bemani/backend/iidx/cannonballers.py +++ b/bemani/backend/iidx/cannonballers.py @@ -3,8 +3,6 @@ import copy import random import struct from typing import Optional, Dict, Any, List, Tuple -from datetime import datetime -from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore from bemani.backend.iidx.base import IIDXBase from bemani.backend.iidx.course import IIDXCourse @@ -1340,11 +1338,6 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase): return root def handle_IIDX25pc_eaappliresult_request(self, request: Node) -> Node: - # first, we register the iidx webhook. this is done by sending all of our money to konami - if self.config['webhooks'][self.game] is None: - return Node.void('IIDX25pc') - webhook = DiscordWebhook(url=self.config['webhooks'][self.game]) - clear_map = { self.GAME_CLEAR_STATUS_NO_PLAY: 'NO PLAY', self.GAME_CLEAR_STATUS_FAILED: 'FAILED', @@ -1390,47 +1383,39 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase): now_clear_string = clear_map.get(now_clear, 'NO PLAY') # let's get the song info first song = self.data.local.music.get_song(self.game, self.music_version, music_id, class_id) + notecount = song.data.get('notecount', 0) + # Construct the dictionary for the broadcast + card_data = { + 'DJ Name': name, + 'Song': song.name, + 'Artist': song.artist, + 'Difficulty': song.data.get('difficulty', 0), + 'Target EXScore': target_exscore, + 'Your EXScore': now_exscore, + 'Best Clear': best_clear_string, + 'Clear Status': now_clear_string, + 'Play Stats': 'How did you do?', + 'Perfect Greats': now_pgreat, + 'Greats': now_great, + 'Goods': now_good, + 'Bads': now_bad, + 'Poors': now_poor, + 'Combo Breaks': now_combo, + 'Slow': now_slow, + 'Fast': now_fast, + } + if notecount != 0: + max_score = notecount * 2 + percent = now_exscore / max_score + grade = int(9 * percent) + grades = ['F', 'F', 'E', 'D', 'C', 'B', 'A', 'AA', 'AAA', 'MAX'] + card_data['Grade'] = grades[grade] + card_data['Score Rate'] = str(round(percent, 2)) - # now we will build up the embed - now = datetime.now() + # Try to broadcast out the score to our webhook(s) + self.data.triggers.broadcast_score(card_data, self.game, song) - # now, we generate the embed - scoreembed = DiscordEmbed(title='New IIDX Score!', description="Login to see whole score.", color='fbba08') - scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S'))) - - # lets give it an author - scoreembed.set_author(name=self.config['name'], url=self.config['server']['uri']) - # Set `inline=False` for the embed field to occupy the whole line - scoreembed.add_embed_field(name='DJ Name', value=(name), inline=False) - scoreembed.add_embed_field(name='Song', value=(song.name), inline=False) - scoreembed.add_embed_field(name='Artist', value=(song.artist), inline=False) - scoreembed.add_embed_field(name='Difficulty', value=(song.data.get('difficulty', 0))) - scoreembed.add_embed_field(name='Target EXScore', value=(target_exscore)) - scoreembed.add_embed_field(name='Your EXScore', value=(now_exscore)) - scoreembed.add_embed_field(name='Best Clear', value=best_clear_string) - scoreembed.add_embed_field(name='Clear Status', value=now_clear_string) - scoreembed.add_embed_field(name='Note Counts', value='How did you do?', inline=False) - scoreembed.add_embed_field(name=('Perfect Greats'), value=((now_pgreat))) - scoreembed.add_embed_field(name=('Greats'), value=((now_great))) - scoreembed.add_embed_field(name=('Goods'), value=((now_good))) - scoreembed.add_embed_field(name=('Bads'), value=((now_bad))) - scoreembed.add_embed_field(name=('Poors'), value=((now_poor))) - - scoreembed.add_embed_field(name='Combo Breaks', value=(now_combo)) - - # scoreembed.add_embed_field(name='Timing Stats', value='Were you on time?', inline = False) - scoreembed.add_embed_field(name=('Slow'), value=((now_slow))) - scoreembed.add_embed_field(name=('Fast'), value=((now_fast))) - - # add embed object to webhook - webhook.add_embed(scoreembed) - - # now we send the webhook! - webhook.execute() - - end = Node.void('IIDX25pc') - - return end + return Node.void('IIDX25pc') def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node: root = Node.void('IIDX25pc') @@ -1868,6 +1853,7 @@ class IIDXCannonBallers(IIDXCourse, IIDXBase): nostalgia = Node.void('nostalgia_open') root.add_child(nostalgia) + # Ea app features root.add_child(Node.void('bind_eaappli')) pay_per_use = Node.void('pay_per_use') root.add_child(pay_per_use) diff --git a/bemani/backend/iidx/copula.py b/bemani/backend/iidx/copula.py index f859f99..c5b2980 100644 --- a/bemani/backend/iidx/copula.py +++ b/bemani/backend/iidx/copula.py @@ -3,8 +3,6 @@ import copy import random import struct from typing import Optional, Dict, Any, List, Tuple -from datetime import datetime -from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore from bemani.backend.iidx.base import IIDXBase from bemani.backend.iidx.course import IIDXCourse @@ -1392,11 +1390,6 @@ class IIDXCopula(IIDXCourse, IIDXBase): return None def handle_IIDX23pc_eaappliresult_request(self, request: Node) -> Node: - # first, we register the iidx webhook. this is done by sending all of our money to konami - if self.config['webhooks'][self.game] is None: - return Node.void('IIDX23pc') - webhook = DiscordWebhook(url=self.config['webhooks'][self.game]) - clear_map = { self.GAME_CLEAR_STATUS_NO_PLAY: 'NO PLAY', self.GAME_CLEAR_STATUS_FAILED: 'FAILED', @@ -1442,47 +1435,39 @@ class IIDXCopula(IIDXCourse, IIDXBase): now_clear_string = clear_map.get(now_clear, 'NO PLAY') # let's get the song info first song = self.data.local.music.get_song(self.game, self.music_version, music_id, class_id) + notecount = song.data.get('notecount', 0) + # Construct the dictionary for the broadcast + card_data = { + 'DJ Name': name, + 'Song': song.name, + 'Artist': song.artist, + 'Difficulty': song.data.get('difficulty', 0), + 'Target EXScore': target_exscore, + 'Your EXScore': now_exscore, + 'Best Clear': best_clear_string, + 'Clear Status': now_clear_string, + 'Play Stats': 'How did you do?', + 'Perfect Greats': now_pgreat, + 'Greats': now_great, + 'Goods': now_good, + 'Bads': now_bad, + 'Poors': now_poor, + 'Combo Breaks': now_combo, + 'Slow': now_slow, + 'Fast': now_fast, + } + if notecount != 0: + max_score = notecount * 2 + percent = now_exscore / max_score + grade = int(9 * percent) + grades = ['F', 'F', 'E', 'D', 'C', 'B', 'A', 'AA', 'AAA', 'MAX'] + card_data['Grade'] = grades[grade] + card_data['Score Rate'] = str(round(percent, 2)) - # now we will build up the embed - now = datetime.now() + # Try to broadcast out the score to our webhook(s) + self.data.triggers.broadcast_score(card_data, self.game, song) - # now, we generate the embed - scoreembed = DiscordEmbed(title='New IIDX Score!', description="Login to see whole score.", color='fbba08') - scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S'))) - - # lets give it an author - scoreembed.set_author(name=self.config['name'], url=self.config['server']['uri']) - # Set `inline=False` for the embed field to occupy the whole line - scoreembed.add_embed_field(name='DJ Name', value=(name), inline=False) - scoreembed.add_embed_field(name='Song', value=(song.name), inline=False) - scoreembed.add_embed_field(name='Artist', value=(song.artist), inline=False) - scoreembed.add_embed_field(name='Difficulty', value=(song.data.get('difficulty', 0))) - scoreembed.add_embed_field(name='Target EXScore', value=(target_exscore)) - scoreembed.add_embed_field(name='Your EXScore', value=(now_exscore)) - scoreembed.add_embed_field(name='Best Clear', value=best_clear_string) - scoreembed.add_embed_field(name='Clear Status', value=now_clear_string) - scoreembed.add_embed_field(name='Note Counts', value='How did you do?', inline=False) - scoreembed.add_embed_field(name=('Perfect Greats'), value=((now_pgreat))) - scoreembed.add_embed_field(name=('Greats'), value=((now_great))) - scoreembed.add_embed_field(name=('Goods'), value=((now_good))) - scoreembed.add_embed_field(name=('Bads'), value=((now_bad))) - scoreembed.add_embed_field(name=('Poors'), value=((now_poor))) - - scoreembed.add_embed_field(name='Combo Breaks', value=(now_combo)) - - # scoreembed.add_embed_field(name='Timing Stats', value='Were you on time?', inline = False) - scoreembed.add_embed_field(name=('Slow'), value=((now_slow))) - scoreembed.add_embed_field(name=('Fast'), value=((now_fast))) - - # add embed object to webhook - webhook.add_embed(scoreembed) - - # now we send the webhook! - webhook.execute() - - end = Node.void('IIDX23pc') - - return end + return Node.void('IIDX23pc') def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node: root = Node.void('IIDX23pc') @@ -1880,6 +1865,8 @@ class IIDXCopula(IIDXCourse, IIDXBase): onemore_data.set_attribute('challenge_num_h', str(onemore_dict.get_int('challenge_num_h'))) onemore_data.set_attribute('challenge_num_a', str(onemore_dict.get_int('challenge_num_a'))) + # Ea app features + root.add_child(Node.void('bind_eaappli')) return root def unformat_profile(self, userid: UserID, request: Node, oldprofile: ValidatedDict) -> ValidatedDict: diff --git a/bemani/backend/iidx/pendual.py b/bemani/backend/iidx/pendual.py index e666719..93b8828 100644 --- a/bemani/backend/iidx/pendual.py +++ b/bemani/backend/iidx/pendual.py @@ -3,8 +3,6 @@ import copy import random import struct from typing import Optional, Dict, Any, List, Tuple -from datetime import datetime -from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore from bemani.backend.iidx.base import IIDXBase from bemani.backend.iidx.course import IIDXCourse @@ -1305,11 +1303,6 @@ class IIDXPendual(IIDXCourse, IIDXBase): return None def handle_IIDX22pc_eaappliresult_request(self, request: Node) -> Node: - # first, we register the iidx webhook. this is done by sending all of our money to konami - if self.config['webhooks'][self.game] is None: - return Node.void('IIDX22pc') - webhook = DiscordWebhook(url=self.config['webhooks'][self.game]) - clear_map = { self.GAME_CLEAR_STATUS_NO_PLAY: 'NO PLAY', self.GAME_CLEAR_STATUS_FAILED: 'FAILED', @@ -1355,47 +1348,39 @@ class IIDXPendual(IIDXCourse, IIDXBase): now_clear_string = clear_map.get(now_clear, 'NO PLAY') # let's get the song info first song = self.data.local.music.get_song(self.game, self.music_version, music_id, class_id) + notecount = song.data.get('notecount', 0) + # Construct the dictionary for the broadcast + card_data = { + 'DJ Name': name, + 'Song': song.name, + 'Artist': song.artist, + 'Difficulty': song.data.get('difficulty', 0), + 'Target EXScore': target_exscore, + 'Your EXScore': now_exscore, + 'Best Clear': best_clear_string, + 'Clear Status': now_clear_string, + 'Play Stats': 'How did you do?', + 'Perfect Greats': now_pgreat, + 'Greats': now_great, + 'Goods': now_good, + 'Bads': now_bad, + 'Poors': now_poor, + 'Combo Breaks': now_combo, + 'Slow': now_slow, + 'Fast': now_fast, + } + if notecount != 0: + max_score = notecount * 2 + percent = now_exscore / max_score + grade = int(9 * percent) + grades = ['F', 'F', 'E', 'D', 'C', 'B', 'A', 'AA', 'AAA', 'MAX'] + card_data['Grade'] = grades[grade] + card_data['Score Rate'] = str(round(percent, 2)) - # now we will build up the embed - now = datetime.now() + # Try to broadcast out the score to our webhook(s) + self.data.triggers.broadcast_score(card_data, self.game, song) - # now, we generate the embed - scoreembed = DiscordEmbed(title='New IIDX Score!', description="Login to see whole score.", color='fbba08') - scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S'))) - - # lets give it an author - scoreembed.set_author(name=self.config['name'], url=self.config['server']['uri']) - # Set `inline=False` for the embed field to occupy the whole line - scoreembed.add_embed_field(name='DJ Name', value=(name), inline=False) - scoreembed.add_embed_field(name='Song', value=(song.name), inline=False) - scoreembed.add_embed_field(name='Artist', value=(song.artist), inline=False) - scoreembed.add_embed_field(name='Difficulty', value=(song.data.get('difficulty', 0))) - scoreembed.add_embed_field(name='Target EXScore', value=(target_exscore)) - scoreembed.add_embed_field(name='Your EXScore', value=(now_exscore)) - scoreembed.add_embed_field(name='Best Clear', value=best_clear_string) - scoreembed.add_embed_field(name='Clear Status', value=now_clear_string) - scoreembed.add_embed_field(name='Note Counts', value='How did you do?', inline=False) - scoreembed.add_embed_field(name=('Perfect Greats'), value=((now_pgreat))) - scoreembed.add_embed_field(name=('Greats'), value=((now_great))) - scoreembed.add_embed_field(name=('Goods'), value=((now_good))) - scoreembed.add_embed_field(name=('Bads'), value=((now_bad))) - scoreembed.add_embed_field(name=('Poors'), value=((now_poor))) - - scoreembed.add_embed_field(name='Combo Breaks', value=(now_combo)) - - # scoreembed.add_embed_field(name='Timing Stats', value='Were you on time?', inline = False) - scoreembed.add_embed_field(name=('Slow'), value=((now_slow))) - scoreembed.add_embed_field(name=('Fast'), value=((now_fast))) - - # add embed object to webhook - webhook.add_embed(scoreembed) - - # now we send the webhook! - webhook.execute() - - end = Node.void('IIDX22pc') - - return end + return Node.void('IIDX22pc') def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node: root = Node.void('IIDX22pc') @@ -1726,6 +1711,8 @@ class IIDXPendual(IIDXCourse, IIDXBase): root.add_child(orb_data) orb_data.set_attribute('rest_orb', str(profile.get_int('orbs'))) + # Ea app features + root.add_child(Node.void('bind_eaappli')) return root def unformat_profile(self, userid: UserID, request: Node, oldprofile: ValidatedDict) -> ValidatedDict: diff --git a/bemani/backend/iidx/rootage.py b/bemani/backend/iidx/rootage.py index eed45fa..051fb70 100644 --- a/bemani/backend/iidx/rootage.py +++ b/bemani/backend/iidx/rootage.py @@ -3,8 +3,6 @@ import copy import random import struct from typing import Optional, Dict, Any, List, Tuple -from datetime import datetime -from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore from bemani.backend.iidx.base import IIDXBase from bemani.backend.iidx.course import IIDXCourse @@ -978,11 +976,6 @@ class IIDXRootage(IIDXCourse, IIDXBase): return Node.void('IIDX26pc') def handle_IIDX26pc_eaappliresult_request(self, request: Node) -> Node: - # first, we register the iidx webhook. this is done by sending all of our money to konami - if self.config['webhooks'][self.game] is None: - return Node.void('IIDX26pc') - webhook = DiscordWebhook(url=self.config['webhooks'][self.game]) - clear_map = { self.GAME_CLEAR_STATUS_NO_PLAY: 'NO PLAY', self.GAME_CLEAR_STATUS_FAILED: 'FAILED', @@ -1028,47 +1021,39 @@ class IIDXRootage(IIDXCourse, IIDXBase): now_clear_string = clear_map.get(now_clear, 'NO PLAY') # let's get the song info first song = self.data.local.music.get_song(self.game, self.music_version, music_id, class_id) + notecount = song.data.get('notecount', 0) + # Construct the dictionary for the broadcast + card_data = { + 'DJ Name': name, + 'Song': song.name, + 'Artist': song.artist, + 'Difficulty': song.data.get('difficulty', 0), + 'Target EXScore': target_exscore, + 'Your EXScore': now_exscore, + 'Best Clear': best_clear_string, + 'Clear Status': now_clear_string, + 'Play Stats': 'How did you do?', + 'Perfect Greats': now_pgreat, + 'Greats': now_great, + 'Goods': now_good, + 'Bads': now_bad, + 'Poors': now_poor, + 'Combo Breaks': now_combo, + 'Slow': now_slow, + 'Fast': now_fast, + } + if notecount != 0: + max_score = notecount * 2 + percent = now_exscore / max_score + grade = int(9 * percent) + grades = ['F', 'F', 'E', 'D', 'C', 'B', 'A', 'AA', 'AAA', 'MAX'] + card_data['Grade'] = grades[grade] + card_data['Score Rate'] = str(round(percent, 2)) - # now we will build up the embed - now = datetime.now() + # Try to broadcast out the score to our webhook(s) + self.data.triggers.broadcast_score(card_data, self.game, song) - # now, we generate the embed - scoreembed = DiscordEmbed(title='New IIDX Score!', description="Login to see whole score.", color='fbba08') - scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S'))) - - # lets give it an author - scoreembed.set_author(name=self.config['name'], url=self.config['server']['uri']) - # Set `inline=False` for the embed field to occupy the whole line - scoreembed.add_embed_field(name='DJ Name', value=(name), inline=False) - scoreembed.add_embed_field(name='Song', value=(song.name), inline=False) - scoreembed.add_embed_field(name='Artist', value=(song.artist), inline=False) - scoreembed.add_embed_field(name='Difficulty', value=(song.data.get('difficulty', 0))) - scoreembed.add_embed_field(name='Target EXScore', value=(target_exscore)) - scoreembed.add_embed_field(name='Your EXScore', value=(now_exscore)) - scoreembed.add_embed_field(name='Best Clear', value=best_clear_string) - scoreembed.add_embed_field(name='Clear Status', value=now_clear_string) - scoreembed.add_embed_field(name='Note Counts', value='How did you do?', inline=False) - scoreembed.add_embed_field(name=('Perfect Greats'), value=((now_pgreat))) - scoreembed.add_embed_field(name=('Greats'), value=((now_great))) - scoreembed.add_embed_field(name=('Goods'), value=((now_good))) - scoreembed.add_embed_field(name=('Bads'), value=((now_bad))) - scoreembed.add_embed_field(name=('Poors'), value=((now_poor))) - - scoreembed.add_embed_field(name='Combo Breaks', value=(now_combo)) - - # scoreembed.add_embed_field(name='Timing Stats', value='Were you on time?', inline = False) - scoreembed.add_embed_field(name=('Slow'), value=((now_slow))) - scoreembed.add_embed_field(name=('Fast'), value=((now_fast))) - - # add embed object to webhook - webhook.add_embed(scoreembed) - - # now we send the webhook! - webhook.execute() - - end = Node.void('IIDX26pc') - - return end + return Node.void('IIDX26pc') def handle_IIDX26gameSystem_systemInfo_request(self, request: Node) -> Node: root = Node.void('IIDX26gameSystem') @@ -1579,6 +1564,7 @@ class IIDXRootage(IIDXCourse, IIDXBase): nostalgia = Node.void('nostalgia_open') root.add_child(nostalgia) + # Ea app features root.add_child(Node.void('bind_eaappli')) pay_per_use = Node.void('pay_per_use') root.add_child(pay_per_use) diff --git a/bemani/backend/iidx/sinobuz.py b/bemani/backend/iidx/sinobuz.py index 91b3f8f..7f2183c 100644 --- a/bemani/backend/iidx/sinobuz.py +++ b/bemani/backend/iidx/sinobuz.py @@ -3,8 +3,6 @@ import copy import random import struct from typing import Optional, Dict, Any, List, Tuple -from datetime import datetime -from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore from bemani.backend.iidx.base import IIDXBase from bemani.backend.iidx.course import IIDXCourse @@ -1364,11 +1362,6 @@ class IIDXSinobuz(IIDXCourse, IIDXBase): return Node.void('IIDX24pc') def handle_IIDX24pc_eaappliresult_request(self, request: Node) -> Node: - # first, we register the iidx webhook. this is done by sending all of our money to konami - if self.config['webhooks'][self.game] is None: - return Node.void('IIDX24pc') - webhook = DiscordWebhook(url=self.config['webhooks'][self.game]) - clear_map = { self.GAME_CLEAR_STATUS_NO_PLAY: 'NO PLAY', self.GAME_CLEAR_STATUS_FAILED: 'FAILED', @@ -1414,47 +1407,39 @@ class IIDXSinobuz(IIDXCourse, IIDXBase): now_clear_string = clear_map.get(now_clear, 'NO PLAY') # let's get the song info first song = self.data.local.music.get_song(self.game, self.music_version, music_id, class_id) + notecount = song.data.get('notecount', 0) + # Construct the dictionary for the broadcast + card_data = { + 'DJ Name': name, + 'Song': song.name, + 'Artist': song.artist, + 'Difficulty': song.data.get('difficulty', 0), + 'Target EXScore': target_exscore, + 'Your EXScore': now_exscore, + 'Best Clear': best_clear_string, + 'Clear Status': now_clear_string, + 'Play Stats': 'How did you do?', + 'Perfect Greats': now_pgreat, + 'Greats': now_great, + 'Goods': now_good, + 'Bads': now_bad, + 'Poors': now_poor, + 'Combo Breaks': now_combo, + 'Slow': now_slow, + 'Fast': now_fast, + } + if notecount != 0: + max_score = notecount * 2 + percent = now_exscore / max_score + grade = int(9 * percent) + grades = ['F', 'F', 'E', 'D', 'C', 'B', 'A', 'AA', 'AAA', 'MAX'] + card_data['Grade'] = grades[grade] + card_data['Score Rate'] = str(round(percent, 2)) - # now we will build up the embed - now = datetime.now() + # Try to broadcast out the score to our webhook(s) + self.data.triggers.broadcast_score(card_data, self.game, song) - # now, we generate the embed - scoreembed = DiscordEmbed(title='New IIDX Score!', description="Login to see whole score.", color='fbba08') - scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S'))) - - # lets give it an author - scoreembed.set_author(name=self.config['name'], url=self.config['server']['uri']) - # Set `inline=False` for the embed field to occupy the whole line - scoreembed.add_embed_field(name='DJ Name', value=(name), inline=False) - scoreembed.add_embed_field(name='Song', value=(song.name), inline=False) - scoreembed.add_embed_field(name='Artist', value=(song.artist), inline=False) - scoreembed.add_embed_field(name='Difficulty', value=(song.data.get('difficulty', 0))) - scoreembed.add_embed_field(name='Target EXScore', value=(target_exscore)) - scoreembed.add_embed_field(name='Your EXScore', value=(now_exscore)) - scoreembed.add_embed_field(name='Best Clear', value=best_clear_string) - scoreembed.add_embed_field(name='Clear Status', value=now_clear_string) - scoreembed.add_embed_field(name='Note Counts', value='How did you do?', inline=False) - scoreembed.add_embed_field(name=('Perfect Greats'), value=((now_pgreat))) - scoreembed.add_embed_field(name=('Greats'), value=((now_great))) - scoreembed.add_embed_field(name=('Goods'), value=((now_good))) - scoreembed.add_embed_field(name=('Bads'), value=((now_bad))) - scoreembed.add_embed_field(name=('Poors'), value=((now_poor))) - - scoreembed.add_embed_field(name='Combo Breaks', value=(now_combo)) - - # scoreembed.add_embed_field(name='Timing Stats', value='Were you on time?', inline = False) - scoreembed.add_embed_field(name=('Slow'), value=((now_slow))) - scoreembed.add_embed_field(name=('Fast'), value=((now_fast))) - - # add embed object to webhook - webhook.add_embed(scoreembed) - - # now we send the webhook! - webhook.execute() - - end = Node.void('IIDX24pc') - - return end + return Node.void('IIDX24pc') def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node: root = Node.void('IIDX24pc') @@ -1891,6 +1876,8 @@ class IIDXSinobuz(IIDXCourse, IIDXBase): nostalgia = Node.void('nostalgia_open') root.add_child(nostalgia) + # Ea app features + root.add_child(Node.void('bind_eaappli')) return root def unformat_profile(self, userid: UserID, request: Node, oldprofile: ValidatedDict) -> ValidatedDict: diff --git a/bemani/backend/iidx/spada.py b/bemani/backend/iidx/spada.py index 3a7cd5d..f076537 100644 --- a/bemani/backend/iidx/spada.py +++ b/bemani/backend/iidx/spada.py @@ -3,8 +3,6 @@ import copy import random import struct from typing import Optional, Dict, List, Tuple, Any -from datetime import datetime -from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore from bemani.backend.iidx.base import IIDXBase from bemani.backend.iidx.tricoro import IIDXTricoro @@ -1004,11 +1002,6 @@ class IIDXSpada(IIDXBase): return None def handle_IIDX21pc_eaappliresult_request(self, request: Node) -> Node: - # first, we register the iidx webhook. this is done by sending all of our money to konami - if self.config['webhooks'][self.game] is None: - return Node.void('IIDX21pc') - webhook = DiscordWebhook(url=self.config['webhooks'][self.game]) - clear_map = { self.GAME_CLEAR_STATUS_NO_PLAY: 'NO PLAY', self.GAME_CLEAR_STATUS_FAILED: 'FAILED', @@ -1054,47 +1047,39 @@ class IIDXSpada(IIDXBase): now_clear_string = clear_map.get(now_clear, 'NO PLAY') # let's get the song info first song = self.data.local.music.get_song(self.game, self.music_version, music_id, class_id) + notecount = song.data.get('notecount', 0) + # Construct the dictionary for the broadcast + card_data = { + 'DJ Name': name, + 'Song': song.name, + 'Artist': song.artist, + 'Difficulty': song.data.get('difficulty', 0), + 'Target EXScore': target_exscore, + 'Your EXScore': now_exscore, + 'Best Clear': best_clear_string, + 'Clear Status': now_clear_string, + 'Play Stats': 'How did you do?', + 'Perfect Greats': now_pgreat, + 'Greats': now_great, + 'Goods': now_good, + 'Bads': now_bad, + 'Poors': now_poor, + 'Combo Breaks': now_combo, + 'Slow': now_slow, + 'Fast': now_fast, + } + if notecount != 0: + max_score = notecount * 2 + percent = now_exscore / max_score + grade = int(9 * percent) + grades = ['F', 'F', 'E', 'D', 'C', 'B', 'A', 'AA', 'AAA', 'MAX'] + card_data['Grade'] = grades[grade] + card_data['Score Rate'] = str(round(percent, 2)) - # now we will build up the embed - now = datetime.now() + # Try to broadcast out the score to our webhook(s) + self.data.triggers.broadcast_score(card_data, self.game, song) - # now, we generate the embed - scoreembed = DiscordEmbed(title='New IIDX Score!', description="Login to see whole score.", color='fbba08') - scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S'))) - - # lets give it an author - scoreembed.set_author(name=self.config['name'], url=self.config['server']['uri']) - # Set `inline=False` for the embed field to occupy the whole line - scoreembed.add_embed_field(name='DJ Name', value=(name), inline=False) - scoreembed.add_embed_field(name='Song', value=(song.name), inline=False) - scoreembed.add_embed_field(name='Artist', value=(song.artist), inline=False) - scoreembed.add_embed_field(name='Difficulty', value=(song.data.get('difficulty', 0))) - scoreembed.add_embed_field(name='Target EXScore', value=(target_exscore)) - scoreembed.add_embed_field(name='Your EXScore', value=(now_exscore)) - scoreembed.add_embed_field(name='Best Clear', value=best_clear_string) - scoreembed.add_embed_field(name='Clear Status', value=now_clear_string) - scoreembed.add_embed_field(name='Note Counts', value='How did you do?', inline=False) - scoreembed.add_embed_field(name=('Perfect Greats'), value=((now_pgreat))) - scoreembed.add_embed_field(name=('Greats'), value=((now_great))) - scoreembed.add_embed_field(name=('Goods'), value=((now_good))) - scoreembed.add_embed_field(name=('Bads'), value=((now_bad))) - scoreembed.add_embed_field(name=('Poors'), value=((now_poor))) - - scoreembed.add_embed_field(name='Combo Breaks', value=(now_combo)) - - # scoreembed.add_embed_field(name='Timing Stats', value='Were you on time?', inline = False) - scoreembed.add_embed_field(name=('Slow'), value=((now_slow))) - scoreembed.add_embed_field(name=('Fast'), value=((now_fast))) - - # add embed object to webhook - webhook.add_embed(scoreembed) - - # now we send the webhook! - webhook.execute() - - end = Node.void('IIDX21pc') - - return end + return Node.void('IIDX21pc') def format_profile(self, userid: UserID, profile: ValidatedDict) -> Node: root = Node.void('IIDX21pc') @@ -1475,6 +1460,8 @@ class IIDXSpada(IIDXBase): if 'durability' in boss1_dict: boss1.add_child(Node.binary('durability', boss1_dict.get_bytes('durability'))) + # Ea app features + root.add_child(Node.void('bind_eaappli')) return root def unformat_profile(self, userid: UserID, request: Node, oldprofile: ValidatedDict) -> ValidatedDict: diff --git a/bemani/data/__init__.py b/bemani/data/__init__.py index b4aeccd..da03e2e 100644 --- a/bemani/data/__init__.py +++ b/bemani/data/__init__.py @@ -2,6 +2,7 @@ from bemani.data.data import Data, DBCreateException from bemani.data.exceptions import ScoreSaveException from bemani.data.types import User, Achievement, Machine, Arcade, Score, Attempt, News, Link, Song, Event, Server, Client, UserID, ArcadeID from bemani.data.remoteuser import RemoteUser +from bemani.data.triggers import Triggers __all__ = [ @@ -23,4 +24,5 @@ __all__ = [ "UserID", "ArcadeID", "RemoteUser", + "Triggers", ] diff --git a/bemani/data/data.py b/bemani/data/data.py index c957e33..955b214 100644 --- a/bemani/data/data.py +++ b/bemani/data/data.py @@ -22,6 +22,7 @@ from bemani.data.mysql.game import GameData from bemani.data.mysql.network import NetworkData from bemani.data.mysql.lobby import LobbyData from bemani.data.mysql.api import APIData +from bemani.data.triggers import Triggers class DBCreateException(Exception): @@ -118,6 +119,7 @@ class Data: self.__api, ) self.remote = GlobalProvider(self.local) + self.triggers = Triggers(config) @classmethod def sqlalchemy_url(cls, config: Dict[str, Any]) -> str: diff --git a/bemani/data/triggers.py b/bemani/data/triggers.py new file mode 100644 index 0000000..e40489a --- /dev/null +++ b/bemani/data/triggers.py @@ -0,0 +1,37 @@ +from bemani.common.constants import GameConstants +from bemani.data.types import Song +from typing import Any, Dict +from discord_webhook import DiscordWebhook, DiscordEmbed # type: ignore +from datetime import datetime + + +class Triggers: + """ + Class for broadcasting data to some outside service + """ + def __init__(self, config: Dict[str, Any]): + self.config = config + + def broadcast_score(self, data: Dict[str, str], game: str, song: Song) -> None: + # For now we only support discord + if self.config.get('webhooks', {}).get('discord', {}).get(game, None) is not None: + self.broadcast_score_discord(data, game, song) + + def broadcast_score_discord(self, data: Dict[str, str], game: str, song: Song) -> None: + if game == GameConstants.IIDX: + now = datetime.now() + + webhook = DiscordWebhook(url=self.config['webhooks']['discord'][game]) + scoreembed = DiscordEmbed(title=f'New {game} Score!', color='fbba08') + scoreembed.set_footer(text=(now.strftime('Score was recorded on %m/%d/%y at %H:%M:%S'))) + + # lets give it an author + song_url = f"{self.config['server']['uri']}/{game}/topscores/{song.id}" if self.config['server']['uri'] is not None else None + scoreembed.set_author(name=self.config['name'], url=song_url) + for item in data: + inline = True + if item in ['DJ Name', 'Song', 'Artist', 'Play Stats']: + inline = False + scoreembed.add_embed_field(name=item, value=data[item], inline=inline) + webhook.add_embed(scoreembed) + webhook.execute() diff --git a/config/server.yaml b/config/server.yaml index 257fa7e..39757e4 100644 --- a/config/server.yaml +++ b/config/server.yaml @@ -25,9 +25,11 @@ server: # Whether PCBIDs must be added to the network before games will work. enforce_pcbid: False -# Discord webhook urls +# Webhook URLs webhooks: - iidx: "https://discord.com/api/webhooks/1232122131321321321/eauihfafaewfhjaveuijaewuivhjawueihoi" + discord: + iidx: + - "https://discord.com/api/webhooks/1232122131321321321/eauihfafaewfhjaveuijaewuivhjawueihoi" paseli: # Whether PASELI is enabled on the network.