Last active
May 9, 2023 08:09
-
-
Save CarbonGhost/0caf8ce8d4b757a6865f19e520d9b588 to your computer and use it in GitHub Desktop.
Prosperity Discord Link
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// # DISCORD LINK -- created by CarbonGhost // | |
// | |
// This is a Scarpet script for creating a two-way-link for Minecraft and | |
// Discord. The script requires Discarpet (https://modrinth.com/mod/discarpet). | |
// Start by filling in the config below, then load the script with `/script load` | |
// | |
// Latest versions / issues / contact: | |
// https://github.com/prosperitymc/Prosperity-Scripts | |
// Script name: | |
global_script_name = 'discord_link'; | |
// The application ID of your bot found via the Discord dev portal: | |
global_application_id = '0000000000000000000'; | |
// The ID of your chat link's Discord server: | |
global_server_id = '0000000000000000000'; | |
// The webhook you wish to use for your chat link: | |
global_link_webhook_url = 'https://discord.com/api/webhooks/0000000000000000000/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; | |
// The types of messages you wish to be linked. These are in the form of | |
// Minecraft translation keys. You can find more keys in the `en_us.json` | |
// language file in your Minecraft `assets` directory: | |
global_link_message_whitelist = [ | |
'chat.type.text', | |
'chat.type.announcement', | |
'chat.type.emote', | |
'chat.type.advancement.task', | |
'chat.type.advancement.challenge', | |
'chat.type.advancement.goal', | |
'multiplayer.player.joined', | |
'multiplayer.player.joined.renamed', | |
'multiplayer.player.left', | |
'death.attack.anvil', | |
'death.attack.anvil.player', | |
'death.attack.arrow', | |
'death.attack.arrow.item', | |
'death.attack.badRespawnPoint.link', | |
'death.attack.badRespawnPoint.message', | |
'death.attack.cactus', | |
'death.attack.cactus.player', | |
'death.attack.cramming', | |
'death.attack.cramming.player', | |
'death.attack.dragonBreath', | |
'death.attack.dragonBreath.player', | |
'death.attack.drown', | |
'death.attack.drown.player', | |
'death.attack.dryout', | |
'death.attack.dryout.player', | |
'death.attack.even_more_magic', | |
'death.attack.explosion', | |
'death.attack.explosion.player', | |
'death.attack.explosion.player.item', | |
'death.attack.fall', | |
'death.attack.fall.player', | |
'death.attack.fallingBlock', | |
'death.attack.fallingBlock.player', | |
'death.attack.fallingStalactite', | |
'death.attack.fallingStalactite.player', | |
'death.attack.fireball', | |
'death.attack.fireball.item', | |
'death.attack.fireworks', | |
'death.attack.fireworks.item', | |
'death.attack.fireworks.player', | |
'death.attack.flyIntoWall', | |
'death.attack.flyIntoWall.player', | |
'death.attack.freeze', | |
'death.attack.freeze.player', | |
'death.attack.generic', | |
'death.attack.generic.player', | |
'death.attack.hotFloor', | |
'death.attack.hotFloor.player', | |
'death.attack.indirectMagic', | |
'death.attack.indirectMagic.item', | |
'death.attack.inFire', | |
'death.attack.inFire.player', | |
'death.attack.inWall', | |
'death.attack.inWall.player', | |
'death.attack.lava', | |
'death.attack.lava.player', | |
'death.attack.lightningBolt', | |
'death.attack.lightningBolt.player', | |
'death.attack.magic', | |
'death.attack.magic.player', | |
'death.attack.message_too_long', | |
'death.attack.mob', | |
'death.attack.mob.item', | |
'death.attack.onFire', | |
'death.attack.onFire.item', | |
'death.attack.onFire.player', | |
'death.attack.outOfWorld', | |
'death.attack.outOfWorld.player', | |
'death.attack.player', | |
'death.attack.player.item', | |
'death.attack.sonic_boom', | |
'death.attack.sonic_boom.item', | |
'death.attack.sonic_boom.player', | |
'death.attack.stalagmite', | |
'death.attack.stalagmite.player', | |
'death.attack.starve', | |
'death.attack.starve.player', | |
'death.attack.sting', | |
'death.attack.sting.item', | |
'death.attack.sting.player', | |
'death.attack.sweetBerryBush', | |
'death.attack.sweetBerryBush.player', | |
'death.attack.thorns', | |
'death.attack.thorns.item', | |
'death.attack.thrown', | |
'death.attack.thrown.item', | |
'death.attack.trident', | |
'death.attack.trident.item', | |
'death.attack.wither', | |
'death.attack.wither.player', | |
'death.attack.witherSkull', | |
'death.attack.witherSkull.item', | |
'death.fell.accident.generic', | |
'death.fell.accident.ladder', | |
'death.fell.accident.other_climbable', | |
'death.fell.accident.scaffolding', | |
'death.fell.accident.twisting_vines', | |
'death.fell.accident.vines', | |
'death.fell.accident.weeping_vines', | |
'death.fell.assist', | |
'death.fell.assist.item', | |
'death.fell.finish', | |
'death.fell.finish.item', | |
'death.fell.killer', | |
]; | |
// Your server's name: | |
global_mc_server_name = 'Server'; | |
// Your server's icon, or that which you want to be shown on system messages : | |
global_mc_server_icon = 'https://media.discordapp.net/attachments/000000000000000000/0000000000000000000/img.png'; | |
// The service you wish to use for Minecraft avatars, use '%s' as a placeholder | |
// for the player's name: | |
global_avatar_url_service = 'https://minotar.net/avatar/%s.png'; | |
// How verbose the script's logging will be: | |
// → 0: No logging | |
// → 1: Log on startup only | |
// → 2: Log on startup and Discord messages | |
global_log_level = 2; | |
// # SCRIPT -- edit the below script at your own risk // | |
__config() -> { | |
'scope' -> 'global', | |
'bot'-> global_application_id, | |
}; | |
__on_start() -> ( | |
llog(1, 'info', 'Discord link loaded!'); | |
global_next_status_update = tick_time() + 40; | |
); | |
global_webhook = dc_webhook_from_url(global_link_webhook_url); | |
global_link_channel = dc_channel_from_id(global_webhook ~ 'channel' ~ 'id'); | |
global_server = dc_server_from_id(global_server_id); | |
global_message_rate = 0; // In ticks. | |
global_player_count_cache = -1; // Initialize to -1 to force status update the first time. | |
__on_tick() -> ( | |
global_message_rate = 0; | |
if(tick_time() == global_next_status_update, | |
set_status(); | |
global_next_status_update += 100; | |
); | |
); | |
// # CHAT LINK // | |
// Handler for the Minecraft server's system message event. | |
// This code will check that the message is whitelisted in the user config and | |
// if so, will send it to the configured Discord channel. | |
// | |
// If the message is not whitelisted, returns. | |
// Has some special behaivor for certain types of messages, like player joins, | |
// and chat messages. | |
__on_system_message(message, translate) -> ( | |
if(global_link_message_whitelist ~ translate == null, return()); | |
task(_(outer(message), outer(translate)) -> ( | |
message_map = decode_json(encode_json(message)); | |
content = { | |
'content' -> message, | |
'allowed_mentions' -> { | |
'mention_users' -> true, | |
}, | |
}; | |
profile = { | |
'name' -> global_mc_server_name, | |
'avatar' -> global_mc_server_icon, | |
}; | |
// Handle a special case where it is desireable for the user's Minecraft | |
// head to show as the webhook profile: | |
user_profile_match_list = [ | |
'chat.type.text', | |
'chat.type.emote', | |
'multiplayer.player.joined', | |
'multiplayer.player.joined.renamed', | |
'multiplayer.player.left', | |
]; | |
if(user_profile_match_list ~ translate != null, | |
profile = { | |
'name' -> message_map : 'with' : 0 : 'insertion', | |
'avatar' -> str( | |
global_avatar_url_service, message_map : 'with' : 0 : 'insertion' | |
), | |
}; | |
); | |
// Handle a spcial case where you would want the raw message content : | |
raw_text_match_list = [ | |
'chat.type.text', | |
]; | |
if(raw_text_match_list ~ translate != null, | |
content : 'content' = message_map : 'with' : 1 : 'text'; | |
); | |
global_message_rate += 1; | |
dc_send_webhook(global_webhook, content, profile); | |
)); | |
); | |
// Handler for Discord messages. This code checks that the message isn't coming | |
// a bot, or itself, and then sends it to the Minecraft server. | |
// | |
// If a message has attatchments, it will send the first one as a clickable link. | |
__on_discord_message(message) -> ( | |
channel = message ~ 'channel'; | |
user = message ~ 'user'; | |
server = message ~ 'server'; | |
attachments = message ~ 'attachments'; | |
if(channel ~ 'id' != global_link_channel ~ 'id' || | |
user ~ 'id' == webhook_user_id || | |
user ~ 'is_bot' == true || null || | |
user ~ 'is_self' == true || null, | |
return(); | |
); | |
display_name = dc_get_display_name(user, server); | |
for(player('all'), | |
print( | |
player(_), | |
format( | |
// Minecraft chat formatting. Format for the username section of the | |
// message. Provides a hover tooltip which, when clicked, allows the | |
// user to mention a Discord user from Minecraft. | |
str('g <@%s>', display_name), | |
str('^w Mention %s...', display_name), | |
str('?%s ', user ~ 'mention_tag') | |
) | |
// Concat the message content. | |
+ format(str('w %s', message ~ 'content')) | |
// If the message contains attatchments, concat a link to the first one. | |
+ if(length(attachments) != 0, | |
format( | |
'gu [Attatchment]', | |
str('^w %s', attachments : 0 ~ 'url'), | |
str('@%s', attachments : 0 ~ 'url'), | |
); | |
); | |
); | |
); | |
llog( | |
2, | |
'info', | |
str( | |
'<%s (@%s) via Discord> %s', | |
user ~ 'name', | |
user ~ 'id', | |
message ~ 'readable_content' | |
), | |
); | |
); | |
// # PLAYER COUNT STATUS // | |
set_status() -> ( | |
count = length(player('all')); | |
if(count == global_player_count_cache, | |
return(); | |
); | |
global_player_count_cache = count; | |
if(count > 1, | |
s = str('%s players', count); | |
); | |
if(count == 1, | |
s = str('%s player', count); | |
); | |
if(count == 0, | |
s = 'no players'; | |
); | |
dc_set_activity('watching', s); | |
); | |
// # UTILS // | |
llog(level, kind, message) -> ( | |
if(global_log_level >= level, | |
logger(kind, str('[%s.sc] %s', global_script_name, message)); | |
); | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment