Compare commits

..

24 commits

Author SHA1 Message Date
56e4e8fe7c
fix: fixed requirements 2023-08-07 17:56:23 -04:00
34a9759a67
feat: discord.py 2.0 compat 2023-08-07 17:56:19 -04:00
09bdf4768e
fix: fixed new_guild_generation again 2023-08-01 18:09:07 -04:00
78ce22aa72
fixed new_guild_generation being called improperly 2023-08-01 18:06:54 -04:00
3af564f9cd
fix: changing stuff in the new_guild_generation method 2023-08-01 18:05:49 -04:00
074569465b
cleanup: removed useless variable 2023-08-01 18:04:03 -04:00
53d1d20942
fix: refactored new_guild_generation 2023-08-01 18:03:45 -04:00
b0c32a130b
fix: no longer using inflect 2023-08-01 17:58:31 -04:00
8759ee1820
fix: added dependency requirement to info.json 2023-08-01 17:52:56 -04:00
d51f42289b
feat: refactored balance command 2023-08-01 17:52:14 -04:00
2173998ced
fix: removing useless data 2023-08-01 17:37:25 -04:00
SeaswimmerTheFsh
6c150045f5 making sure galaxy.py is updated on this 2023-03-16 17:04:11 -04:00
SeaswimmerTheFsh
b241606796 Update sugoncredit.py 2023-03-16 16:30:22 -04:00
SeaswimmerTheFsh
2169436a70 Update sugoncredit.py 2023-03-15 11:59:46 -04:00
SeaswimmerTheFsh
691cacbbc6 Update sugoncredit.py 2023-03-15 11:45:11 -04:00
SeaswimmerTheFsh
22d9802aa0 fixed a bunch of goofy aah formatting 2023-03-14 22:46:45 -04:00
SeaswimmerTheFsh
680759c5dd WOOOOOO im going insane
changed a bunch of sql stuff
2023-03-14 22:45:13 -04:00
SeaswimmerTheFsh
5aebdc5eed global --> guild 2023-03-14 20:05:21 -04:00
SeaswimmerTheFsh
019f68a1e8 added another check
credit add and credit remove will now check if the new balance is below the minimum balance - on that note, added min_bal as a config option
2023-03-14 19:49:55 -04:00
SeaswimmerTheFsh
8f9c774f68 removed negative check
removed the if statement that checked if the new balance being set was below 0. this allows balances to go below 0
2023-03-14 19:45:50 -04:00
SeaswimmerTheFsh
6c3a7d1e78 Update sugoncredit.py
doing more sql stuff
2023-03-14 19:42:44 -04:00
SeaswimmerTheFsh
6d41ea67e2 Update galaxy.py
made sure galaxy.py is identical to the main branch version in sugoncredit_sql
2023-03-14 18:29:25 -04:00
SeaswimmerTheFsh
87ea3b273e removed import
removed re from imports in galaxy.py as it isn't used
2023-03-14 18:21:45 -04:00
e5656d2aa2 sql version pushed 2023-03-13 21:39:51 -04:00
68 changed files with 491 additions and 4675 deletions

View file

@ -1,23 +0,0 @@
---
name: Bot Bug Report
about: Got an issue with the Galaxy bot? Use this.
title: "[BOT BUG]"
labels: bot, bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
What caused the bug?
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View file

@ -1,23 +0,0 @@
---
name: Bot Suggestion
about: Trying to suggest something for the Galaxy bot? Use this.
title: "[BOT SUGGESTION]"
labels: bot, enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View file

@ -1,23 +0,0 @@
---
name: Cog Bug Report
about: Got an issue with a cog from Galaxy Cogs? Use this.
title: "[COG BUG]"
labels: bug, cog
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
What caused the error?
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View file

@ -1,26 +0,0 @@
---
name: Cog Suggestion
about: Trying to suggest something for Galaxy Cogs? Use this.
title: "[COG SUGGESTION]"
labels: cog, enhancement
assignees: ''
---
**What cog is your feature request for?**
A cog in this repository.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View file

@ -1,16 +0,0 @@
[MESSAGES CONTROL]
disable=
too-many-lines,
missing-module-docstring,
missing-function-docstring,
missing-class-docstring,
line-too-long,
too-many-arguments,
too-many-branches,
superfluous-parens,
invalid-name,
too-many-locals,
too-many-public-methods,
too-many-statements,
arguments-differ,
too-many-return-statements

View file

@ -1,20 +0,0 @@
name: Actions
on:
push:
branches:
- 'main'
pull_request:
jobs:
Lint Code (Pylint):
runs-on: docker
container: www.coastalcommits.com/cswimr/actions:galaxycogs
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install dependencies
run: poetry install --with dev --no-root
- name: Analysing code with Pylint
run: pylint --rcfile .forgejo/workflows/config/.pylintrc $(git ls-files '*.py')

5
.gitignore vendored
View file

@ -1,2 +1,7 @@
galaxy/slashtag arguments.txt
galaxy_server.yaml
global.yaml
galaxy_staff_server.yaml
combat_welder.yaml
.venv
/OOUCogs

View file

@ -1,72 +1,51 @@
# GalaxyCogs
<p align="center">
<a href="https://discord.com/invite/robloxgalaxy">
<img src="https://discordapp.com/api/guilds/204965774618656769/widget.png?style=shield" alt="Galaxy Discord Server">
</a>
<a href="https://www.python.org/downloads/">
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/Red-Discordbot">
</a>
<a href="https://github.com/Rapptz/discord.py/">
<img src="https://img.shields.io/badge/discord-py-blue.svg" alt="discord.py">
</a>
</p>
Repository for Redbot cogs developed by the Galaxy Discord Management team.
**This readme is heavily outdated.**
## ExportChannels **(WIP)**[^incomplete]
This cog allows you to easily export channels using Discord Chat Exporter.
**THIS COG IS NOT INTENDED FOR EXTERNAL USE. YOU WILL LIKELY HAVE TO RUN THIS COG LOCALLY AND MODIFY CODE SHOULD YOU WISH TO USE IT.**
### **Credit to Tyrrrz for the bundled version of Discord Chat Exporter within this cog. The original repository can be found [here](https://github.com/Tyrrrz/DiscordChatExporter).**
## Galaxy
Utility cog designed specifically for use on the Galaxy Discord server.
Utility cog designed specifically for use on the Galaxy Discord server.
Includes:
* Warehouse command
* FAQ command
* Unix command
## Info
Combination of a few built-in Red cogs + some custom code to provide commands that show information of specific Discord objects.
Currently supports:
* Users
* Servers/Guilds
* Roles
* Roles[^dpy_notice]
[^dpy_notice]:
Due to Red's use of Discord.py 1.7.3, the ``[p]roleinfo`` command in the Info cog does not show all permissions. This is due to the outdated Discord.py version not supporting checking for all permissions.
## Podcast **(WIP)**[^incomplete]
## Podcast **(WIP)**
Allows users to submit questions to a specified channel, intended for use with podcasts.
Allows users to submit questions to a specified channel, intended for use with podcasts.
Also features user blacklists, both configurable per-server and globally.
Also features user blacklists, both configurable per-server and globally.
[^incomplete]:
This cog currently is non-functional. This notice will be removed once the Cog is completed.
## Suggestions
Allows users to submit suggestions to a specified channel. Highly cut-down modification of [SauriCog's Suggestions Cog](https://github.com/elijabesu/SauriCogs).
## Shortmute
Allows staff members to shortmute individuals for up to 30 minutes, using Discord's Timeouts feature.
## Suggestions
Allows users to submit suggestions to a specified channel. Highly cut-down modification of [SauriCog's Suggestions Cog](https://github.com/elijabesu/SauriCogs).
Features:
* Separate approved and denied channels
* Custom emoji support
## SugonCredit[^incomplete]
Features:
* Separate approved and denied channels
* Custom emoji support
## SugonCredit
Implements a way for moderators to give out social-credit like points, dubbed 'sugoncredits' by the community.
Features:
* Add Credit to people.
* Remove Credit from people.
* Supports custom currency names and bank names.
## YouTubeDownloader
Allows users to download any YouTube video.
`[p]download https://youtu.be/dQw4w9WgXcQ` - Downloads the audio from [this video](https://youtu.be/dQw4w9WgXcQ) in `.m4a` format.
`[p]download https://youtu.be/dQw4w9WgXcQ false` - Downloads [this video](https://youtu.be/dQw4w9WgXcQ) in `.mp4` format.
* Supports custom currency names and bank names.

View file

@ -1,4 +0,0 @@
from .exportchannels import ExportChannels
async def setup(bot):
await bot.add_cog(ExportChannels(bot))

Binary file not shown.

Binary file not shown.

View file

@ -1,275 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v7.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v7.0": {
"DiscordChatExporter.Cli/2.40.4": {
"dependencies": {
"CliFx": "2.3.4",
"Deorcify": "1.0.2",
"DiscordChatExporter.Core": "2.40.4",
"DotnetRuntimeBootstrapper": "2.5.1",
"Gress": "2.1.1",
"Spectre.Console": "0.47.0"
},
"runtime": {
"DiscordChatExporter.Cli.dll": {}
}
},
"AdvancedStringBuilder/0.1.0": {
"runtime": {
"lib/netstandard2.0/AdvancedStringBuilder.dll": {
"assemblyVersion": "0.1.0.0",
"fileVersion": "0.1.0.0"
}
}
},
"AngleSharp/1.0.4": {
"dependencies": {
"System.Text.Encoding.CodePages": "7.0.0"
},
"runtime": {
"lib/net7.0/AngleSharp.dll": {
"assemblyVersion": "1.0.4.0",
"fileVersion": "1.0.4.0"
}
}
},
"AsyncKeyedLock/6.2.1": {
"runtime": {
"lib/net5.0/AsyncKeyedLock.dll": {
"assemblyVersion": "6.2.1.0",
"fileVersion": "6.2.1.0"
}
}
},
"CliFx/2.3.4": {
"runtime": {
"lib/netstandard2.1/CliFx.dll": {
"assemblyVersion": "2.3.4.0",
"fileVersion": "2.3.4.0"
}
}
},
"Deorcify/1.0.2": {},
"DotnetRuntimeBootstrapper/2.5.1": {},
"Gress/2.1.1": {
"runtime": {
"lib/netstandard2.0/Gress.dll": {
"assemblyVersion": "2.1.1.0",
"fileVersion": "2.1.1.0"
}
}
},
"JsonExtensions/1.2.0": {
"runtime": {
"lib/net5.0/JsonExtensions.dll": {
"assemblyVersion": "1.2.0.0",
"fileVersion": "1.2.0.0"
}
}
},
"Polly/7.2.4": {
"runtime": {
"lib/netstandard2.0/Polly.dll": {
"assemblyVersion": "7.0.0.0",
"fileVersion": "7.2.4.982"
}
}
},
"RazorBlade/0.4.3": {
"runtime": {
"lib/net6.0/RazorBlade.dll": {
"assemblyVersion": "0.4.3.0",
"fileVersion": "0.4.3.0"
}
}
},
"Spectre.Console/0.47.0": {
"dependencies": {
"System.Memory": "4.5.5"
},
"runtime": {
"lib/net7.0/Spectre.Console.dll": {
"assemblyVersion": "0.0.0.0",
"fileVersion": "0.47.0.0"
}
}
},
"Superpower/3.0.0": {
"runtime": {
"lib/net5.0/Superpower.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "3.0.0.0"
}
}
},
"System.Memory/4.5.5": {},
"System.Text.Encoding.CodePages/7.0.0": {},
"WebMarkupMin.Core/2.14.0": {
"dependencies": {
"AdvancedStringBuilder": "0.1.0"
},
"runtime": {
"lib/netstandard2.1/WebMarkupMin.Core.dll": {
"assemblyVersion": "2.14.0.0",
"fileVersion": "2.14.0.0"
}
}
},
"YoutubeExplode/6.3.1": {
"dependencies": {
"AngleSharp": "1.0.4"
},
"runtime": {
"lib/net5.0/YoutubeExplode.dll": {
"assemblyVersion": "6.3.1.0",
"fileVersion": "6.3.1.0"
}
}
},
"DiscordChatExporter.Core/2.40.4": {
"dependencies": {
"AsyncKeyedLock": "6.2.1",
"Gress": "2.1.1",
"JsonExtensions": "1.2.0",
"Polly": "7.2.4",
"RazorBlade": "0.4.3",
"Superpower": "3.0.0",
"WebMarkupMin.Core": "2.14.0",
"YoutubeExplode": "6.3.1"
},
"runtime": {
"DiscordChatExporter.Core.dll": {}
}
}
}
},
"libraries": {
"DiscordChatExporter.Cli/2.40.4": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"AdvancedStringBuilder/0.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-IbN3r5whlJvi8MhCDPVpIb+NVScyUcKSdcJZrnoXFDyzPDISl3AbWouNBYIHRdZdfGuzqCQEhM1vkxbIKqQVaQ==",
"path": "advancedstringbuilder/0.1.0",
"hashPath": "advancedstringbuilder.0.1.0.nupkg.sha512"
},
"AngleSharp/1.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-G8R4C2MEDFQvjUbYz1QIcGfibjsTJnzP0aWy8iQgWWk7eKacYydCNGD3JMhVL0Q5pZQ9RYlqpKNESEU5NpqsRw==",
"path": "anglesharp/1.0.4",
"hashPath": "anglesharp.1.0.4.nupkg.sha512"
},
"AsyncKeyedLock/6.2.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-WUvN3Q7aL3wARMcVi/KYTHjOC+0Ld+/ikKU6UGr4aOl7TuK1I2MNKeUkmfr7y4S3UNjQbpzNQCV2OcJq1S/yXg==",
"path": "asynckeyedlock/6.2.1",
"hashPath": "asynckeyedlock.6.2.1.nupkg.sha512"
},
"CliFx/2.3.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-CFD8yL9McQrKa2dnGdXx/e1ob3QXcVICHpE9XbPXnFw1yPdqAgij3pdS4Xfii3U0+D1HJRW1rOPtNnuR7lI1cQ==",
"path": "clifx/2.3.4",
"hashPath": "clifx.2.3.4.nupkg.sha512"
},
"Deorcify/1.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-khu8MahgfbXc8eQxfZgRX38Jgu1ZLg+6aK906XtIkUpzMovhaPs4ZOWcUiDLtPz0a9m7TcQwtGtoeRgghO8mVw==",
"path": "deorcify/1.0.2",
"hashPath": "deorcify.1.0.2.nupkg.sha512"
},
"DotnetRuntimeBootstrapper/2.5.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Ufbf8Qe9hwY/KojfimWX4Kqka3QFH4IoGiQj8LPRlyk68/ApHxsG+p6GeTwukY0sIgxA1VXUAFkbvnn9rbZyaw==",
"path": "dotnetruntimebootstrapper/2.5.1",
"hashPath": "dotnetruntimebootstrapper.2.5.1.nupkg.sha512"
},
"Gress/2.1.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-n/YK1XYM2xUhoPFRRJpoTk5qtWBwTkSZlWtxqb4JNX3pDfwoMiu6G+zs65y8Z8SfIUxhOhU5yO/v58WkZynECg==",
"path": "gress/2.1.1",
"hashPath": "gress.2.1.1.nupkg.sha512"
},
"JsonExtensions/1.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ujtrK6m5BQVQLEteLfl54upN7Z59c1ZqEKmU3OlYriqnV74dIgIlNM2vkcgn2AuZEItQDNORD/2H1biI/asOdg==",
"path": "jsonextensions/1.2.0",
"hashPath": "jsonextensions.1.2.0.nupkg.sha512"
},
"Polly/7.2.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-bw00Ck5sh6ekduDE3mnCo1ohzuad946uslCDEENu3091+6UKnBuKLo4e+yaNcCzXxOZCXWY2gV4a35+K1d4LDA==",
"path": "polly/7.2.4",
"hashPath": "polly.7.2.4.nupkg.sha512"
},
"RazorBlade/0.4.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-EwoDxG2aw5UuKsxKbg9W8PPlmkvPvp9y7yLjRhfIQvnDRZEfr3n+RCs46VHlIvALbCGDCX3S0B/zKMEmkFLHLQ==",
"path": "razorblade/0.4.3",
"hashPath": "razorblade.0.4.3.nupkg.sha512"
},
"Spectre.Console/0.47.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wz8mszcZr0cSOo8GyoG9e2DFW0SkMT8/n78Q/lIXX7EbCtHNXOoOKWpJ9Str+rCYtmQOGGyDutZzubrUHK/XkA==",
"path": "spectre.console/0.47.0",
"hashPath": "spectre.console.0.47.0.nupkg.sha512"
},
"Superpower/3.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-bjKbAYWePooCAvPxQq+3KnmcLfRggMyRoXmtBMlmCG71bdwBHrO6rmRJ2DRIodg5aztNcxeZXBUVWT+H+MZUhw==",
"path": "superpower/3.0.0",
"hashPath": "superpower.3.0.0.nupkg.sha512"
},
"System.Memory/4.5.5": {
"type": "package",
"serviceable": true,
"sha512": "sha512-XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"path": "system.memory/4.5.5",
"hashPath": "system.memory.4.5.5.nupkg.sha512"
},
"System.Text.Encoding.CodePages/7.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LSyCblMpvOe0N3E+8e0skHcrIhgV2huaNcjUUEa8hRtgEAm36aGkRoC8Jxlb6Ra6GSfF29ftduPNywin8XolzQ==",
"path": "system.text.encoding.codepages/7.0.0",
"hashPath": "system.text.encoding.codepages.7.0.0.nupkg.sha512"
},
"WebMarkupMin.Core/2.14.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-fRydp8dkCWkC3RDL+7ABWLLTgAnFEb5k7flhWrTlyGatg0rpT4HArKnGmfgfQ27FVMa1lCOAzFE1ORF5y5Pzbw==",
"path": "webmarkupmin.core/2.14.0",
"hashPath": "webmarkupmin.core.2.14.0.nupkg.sha512"
},
"YoutubeExplode/6.3.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-+k/RYu3UCI2TwSo/QuIHnhSQ74GRy1gNSuthb/o2ZRNSLidzmbyWaNtBABOxqQJj6ohG/fVScin8cuFVg3Q5vA==",
"path": "youtubeexplode/6.3.1",
"hashPath": "youtubeexplode.6.3.1.nupkg.sha512"
},
"DiscordChatExporter.Core/2.40.4": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This configuration file is required by the apphost which runs on legacy .NET Framework for compatibility reasons -->
<configuration>
<!-- Prefer .NET 3.5 (preinstalled on Windows 7), rollover to .NET 4.x (preinstalled on Windows 8+) -->
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v2.0.50727" />
<supportedRuntime version="v4.0" />
</startup>
</configuration>

View file

@ -1,12 +0,0 @@
{
"runtimeOptions": {
"tfm": "net7.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "7.0.0"
},
"configProperties": {
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
}
}
}

Binary file not shown.

Binary file not shown.

View file

@ -1,2 +0,0 @@
This bundled version of Discord Chat Exporter can be found here: https://github.com/Tyrrrz/DiscordChatExporter/releases/tag/2.40.4
I DID NOT MAKE THIS PROGRAM. This program is developed by Tyrrrz, NOT me.

Binary file not shown.

Binary file not shown.

View file

@ -1,104 +0,0 @@
import asyncio
import os
import discord
from redbot.core import Config, checks, commands, data_manager
class ExportChannels(commands.Cog):
"""Custom cog to export channels to JSON and HTML formats using Discord Chat Exporter.
Developed by cswimr and yname."""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=48258471944753312)
self.config.register_global(
bot_token = None
)
self.data_path = data_manager.cog_data_path(self)
class ConfigException(Exception):
pass
async def export(self, channels: list):
token = await self.config.bot_token()
if token is None:
raise(self.ConfigException("Bot token not set!"))
data_path = data_manager.cog_data_path(self)
bundled_data_path = data_manager.bundled_data_path(self)
out = f'{data_path}{os.sep}Exported Channels'
channel = channels[0]
file_location_html = f'{os.sep}{out}{os.sep}%g{os.sep}%c{os.sep}Export.html'
file_location_json = f'{os.sep}{out}{os.sep}%g{os.sep}%c{os.sep}DCE-f.json'
try:
os.mkdir(out)
except FileExistsError:
pass
args = [
'dotnet',
'DiscordChatExporter.Cli.dll',
'export',
'--format', 'HtmlDark',
'--output', file_location_html,
'--token', token,
'--channel', channel,
'--reuse-media',
'--media',
'--fuck_russia', 'true',
]
os.chdir(bundled_data_path)
process_1 = await asyncio.create_subprocess_exec(*args)
while True:
return_code_1 = process_1.poll()
if return_code_1 is not None:
break
args = [
'dotnet',
'DiscordChatExporter.Cli.dll',
'export',
'--format', 'Json',
'--output', file_location_json,
'--token', token,
'--channel', channels,
'--reuse_media',
'--media',
'--markdown', 'false',
'--fuck_russia', 'true',
]
os.chdir(bundled_data_path)
process_2 = await asyncio.create_subprocess_exec(*args)
while True:
return_code_2 = process_2.poll()
if return_code_2 is not None:
break
@commands.group()
@checks.is_owner()
async def exportset(self, ctx: commands.Context):
"""Configuration options for the ExportChannels cog."""
@exportset.command()
@checks.is_owner()
async def token(self, ctx: commands.Context, token: str):
"""Sets the bot token used for Discord Chat Exporter."""
await self.config.bot_token.set({token})
await ctx.send(content="Token set!")
await ctx.delete()
@exportset.command()
@checks.is_owner()
async def checkoutputpath(self, ctx: commands.Context):
"""Checks what file path DCE is outputting to."""
await ctx.send(content=f"{self.data_path}")
@commands.command()
@commands.admin()
async def exportchannel(self, ctx: commands.Context, channel: discord.TextChannel):
"""Exports a channel using Discord Chat Exporter."""
token = await self.config.bot_token()
if token is None:
await ctx.send(content=f"Please set your token with the ``{ctx.prefix}exportset token`` command!")
return
id_list = [thread.id for thread in channel.threads]
id_list.insert(0, channel.id)
await self.export(id_list)

View file

@ -1,5 +0,0 @@
from .forums import Forums
async def setup(bot):
await bot.add_cog(Forums(bot))

View file

@ -1,208 +0,0 @@
import discord
from discord import ui
from redbot.core import Config, commands
class Forums(commands.Cog):
"""Custom cog intended for use on the Galaxy discord server.
Developed by cswimr."""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=2352711325)
self.config.register_guild(
request_roles=[],
forum_channel=None,
forum_tag=None
)
@commands.command()
@commands.guild_only()
async def resolved(self, ctx: commands.Context, *, reason: str = None):
"""Marks a thread as resolved."""
channel_id = await self.config.guild(ctx.guild).forum_channel()
tag = await self.config.guild(ctx.guild).forum_tag()
request_role_ids = await self.config.guild(ctx.guild).request_roles()
if channel_id is None or tag is None or request_role_ids is None:
await ctx.reply(f"Configuration not set properly! Please set configuration options with `{ctx.prefix}resolvedset`.")
return
if isinstance(ctx.channel, discord.Thread) and ctx.channel.parent_id == channel_id:
request_roles = [ctx.guild.get_role(role_id) for role_id in request_role_ids]
match = any(role in ctx.author.roles for role in request_roles)
passed_info = {
"ctx": ctx
}
if match and reason:
passed_info.update({"reason": reason})
if match or ctx.author.id == ctx.channel.owner.id:
msg = await ctx.send("Are you sure you'd like to mark this thread as resolved?")
passed_info.update({"msg": msg})
await msg.edit(view=self.ResolvedButtons(timeout=180, passed_info=passed_info))
else:
await ctx.message.add_reaction("")
await ctx.message.delete(delay=5)
class ResolvedButtons(ui.View):
def __init__(self, timeout, passed_info: dict):
super().__init__()
self.timeout = timeout
self.ctx: commands.Context = passed_info['ctx']
self.msg: discord.Message = passed_info['msg']
if 'reason' in passed_info:
self.reason: str = passed_info['reason']
else:
self.reason = False
self.config = Config.get_conf(None, cog_name='Forums', identifier=2352711325)
@ui.button(label="Yes", style=discord.ButtonStyle.success, emoji="")
async def resolved_button_yes(self, interaction: discord.Interaction, button: ui.Button): # pylint: disable=unused-argument
request_role_ids = await self.config.guild(interaction.guild).request_roles()
request_roles = [interaction.guild.get_role(role_id) for role_id in request_role_ids]
match = any(role in interaction.user.roles for role in request_roles)
if match or interaction.user.id == interaction.channel.owner.id:
await interaction.response.defer()
if self.reason:
response_reason = f"Thread closed by {interaction.user.mention} with reason: {self.reason}"
reason = f"Thread closed by {interaction.user.name} ({interaction.user.id}) with reason: {self.reason}"
else:
response_reason = f"Thread closed by {interaction.user.mention}"
reason = f"Thread closed by {interaction.user.name} ({interaction.user.id})"
await self.msg.edit(content=response_reason, view=None)
await self.ctx.message.delete()
tag = interaction.channel.parent.get_tag(await self.config.guild(interaction.guild).forum_tag())
if tag in interaction.channel.applied_tags:
await interaction.channel.edit(locked=True, archived=True, reason=reason)
else:
await interaction.channel.edit(locked=True, archived=True, applied_tags=interaction.channel.applied_tags + [tag], reason=reason)
else:
await interaction.response.send_message(content="You cannot close this thread!", ephemeral=True)
@ui.button(label="No", style=discord.ButtonStyle.danger, emoji="✖️")
async def resolved_button_no(self, interaction: discord.Interaction, button: ui.Button): # pylint: disable=unused-argument
request_role_ids = await self.config.guild(interaction.guild).request_roles()
request_roles = [interaction.guild.get_role(role_id) for role_id in request_role_ids]
match = any(role in interaction.user.roles for role in request_roles)
if match or interaction.user.id == interaction.channel.owner.id:
await interaction.response.defer()
await self.msg.delete()
await self.ctx.message.delete()
else:
await interaction.response.send_message(content="You cannot close this thread!", ephemeral=True)
@commands.group(name='resolvedset', autohelp=True, aliases=['resolvedconfig'])
@commands.guild_only()
@commands.admin()
async def resolvedset(self, ctx: commands.Context):
"""Manages the configuration for the [p]resolved command."""
@resolvedset.command(name='show', aliases=['settings'])
async def resolvedset_show(self, ctx: commands.Context):
"""Shows the current cog configuration."""
channel_id = await self.config.guild(ctx.guild).forum_channel()
tag = await self.config.guild(ctx.guild).forum_tag()
request_role_ids = await self.config.guild(ctx.guild).request_roles()
split_content = ctx.message.content.split()
command = ' '.join(split_content[:1])
already_in_list = []
for role_id in request_role_ids:
role_obj = ctx.guild.get_role(role_id)
if role_obj:
already_in_list.append(role_obj.mention)
if already_in_list:
roles_list = "**Allowed Roles**:\n" + "\n".join(already_in_list)
else:
roles_list = f"No roles are currently in the allowed roles list.\n- Use `{command} add` to add some."
tag_str = None
if channel_id is not None:
channel_obj = ctx.guild.get_channel(channel_id)
if channel_obj is None:
channel = f"**Channel**: {channel_id}\n- ⚠️ This channel cannot be found in this guild. Is this the correct ID?\n\n"
else:
channel = f"**Channel**: {channel_obj.mention}\n\n"
if tag is not None:
tag_obj = channel_obj.get_tag(tag)
if tag_obj is None:
tag_str = f"**Tag**: {tag}\n- ⚠️ This tag cannot be found in the set forums channel. Is this the correct ID?\n\n"
else:
tag_str = f"**Tag**: {tag_obj.emoji} {tag_obj.name}\n\n"
else:
channel = f"**Channel**: Not set!\n- Use `{command} channel` to set the forums channel.\n\n"
if tag_str is None:
tag_str = f"**Tag**: Not set!\n- Use `{command} tag` to set the tag.\n\n"
embed = discord.Embed(title="Cog Settings", color=await self.bot.get_embed_color(None), description=channel + tag_str + roles_list)
await ctx.reply(embed=embed)
@resolvedset.group(name='role', autohelp=True, aliases=['roles'])
async def resolvedset_role(self, ctx: commands.Context):
"""Manages the allowed roles list."""
@resolvedset_role.command(name='add')
async def resolvedset_role_add(self, ctx: commands.Context, role: discord.Role = None):
"""Adds roles to the allowed roles list."""
current_list = await self.config.guild(ctx.guild).request_roles()
if role:
if role.id in current_list:
await ctx.send("This role is already in the allowed roles list!")
else:
current_list.append(role.id)
await self.config.guild(ctx.guild).request_roles.set(current_list)
await ctx.send(f"{role.mention} has been added to the allowed roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
else:
await ctx.send("Please provide a valid role.")
@resolvedset_role.command(name='remove')
async def resolvedset_role_remove(self, ctx: commands.Context, role: discord.Role = None):
"""Removes roles from the allowed roles list."""
current_list = await self.config.guild(ctx.guild).request_roles()
if role.id in current_list:
current_list.remove(role.id)
await self.config.guild(ctx.guild).request_roles.set(current_list)
await ctx.send(f"{role.mention} has been removed from the allowed roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
else:
await ctx.send("Please provide a valid role that exists in the allowed roles list.")
def create_select_options(self, ctx: commands.Context, data):
options = []
for tag in data:
emoji = ctx.guild.get_emoji(tag.emoji.id) if tag.emoji.id else str(tag.emoji.name)
options.append(discord.SelectOption(label=tag.name, emoji=emoji, description="", value=tag.id))
return options
@resolvedset.command(name="channel")
async def resolvedset_channel(self, ctx: commands.Context, channel: discord.abc.GuildChannel):
"""Sets the channel used by the [p]resolved command."""
if isinstance(channel, discord.ForumChannel):
await self.config.guild(ctx.guild).forum_channel.set(channel.id)
await ctx.reply(f"Forum channel has been set to {channel.mention}.")
else:
await ctx.reply(f"{channel.mention} is not a forums channel!")
@resolvedset.command(name="tag")
async def resolvedset_tag(self, ctx: commands.Context):
"""Sets the tag used by the [p]resolved command."""
channel: discord.ForumChannel = ctx.guild.get_channel(await self.config.guild(ctx.guild).forum_channel())
if channel is not None:
options = self.create_select_options(ctx, channel.available_tags)
msg = await ctx.reply("Select a forum tag below.")
await msg.edit(view=SelectView(msg, options))
else:
await ctx.reply("Configuration error! Channel does not exist.")
class Select(ui.Select):
def __init__(self, message, options):
self.message = message
super().__init__(placeholder="Select an option", max_values=1, min_values=1, options=options)
async def callback(self, interaction: discord.Interaction):
msg: discord.Message = self.message
config = Config.get_conf(None, cog_name='Forums', identifier=2352711325)
await config.guild(msg.guild).forum_tag.set(int(self.values[0]))
channel: discord.ForumChannel = msg.guild.get_channel(await config.guild(msg.guild).forum_channel())
tag = channel.get_tag(int(self.values[0]))
await msg.edit(content=f"Set resolved tag to {tag.emoji} {tag.name}", view=None)
await interaction.response.defer()
class SelectView(ui.View):
def __init__(self, message, options, *, timeout=180):
super().__init__(timeout=timeout)
self.add_item(Select(message, options))

View file

@ -1,10 +0,0 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing Forums!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"name" : "Forums",
"short" : "Custom cog intended for use on the Galaxy discord server.",
"description" : "Custom cog intended for use on the Galaxy discord server.",
"end_user_data_statement" : "This cog does not store any End User Data.",
"hidden": false,
"disabled": false
}

View file

@ -1,5 +1,5 @@
from .galaxy import Galaxy
async def setup(bot):
await bot.add_cog(Galaxy(bot))
def setup(bot):
bot.add_cog(Galaxy(bot))

View file

@ -1,253 +1,124 @@
import re
from datetime import datetime
from random import randint
from redbot.core import commands, checks, Config, bot
import discord
from redbot.core import Config, app_commands, commands
from redbot.core.app_commands import Choice
from datetime import datetime
import re
class Galaxy(commands.Cog):
"""Custom cog intended for use on the Galaxy discord server.
Developed by cswimr."""
Developed by SeaswimmerTheFsh."""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=6621962)
self.config.register_guild(
autoreact_target = 0,
autoreact_emoji = '💀'
cocotarget = 0,
cocoemoji = 1028535684757209118
)
@commands.command()
async def carnagerefund(self, ctx: commands.Context, message_id: str):
"""This command generates a link to refund carnage of killed ships."""
output = f"https://info.galaxy.casa/kills/{message_id}"
await ctx.send(f"Output link: {output}")
@commands.Cog.listener('on_message')
async def gank_won_let_us_flee(self, message: discord.Message):
if message.author.id == 745790085789909033 and message.guild.id == 204965774618656769 and message.channel.id == 753714180900519937:
gank_media_list = [
"https://cdn.discordapp.com/attachments/1070838419212738621/1155174309711577138/gank_won_let_us_flee.gif",
"https://cdn.discordapp.com/attachments/1070838419212738621/1155174310093262951/spin_back_I_dare_you.jpg",
"https://cdn.discordapp.com/attachments/1070838419212738621/1155174310466572328/spin_back_mutt.gif",
"https://cdn.discordapp.com/attachments/1070838419212738621/1155174310806290533/We_dont_run_1s_around_here.gif"
]
if len(message.embeds) == 1 and str(message.embeds[0].color) == '#57f287':
await message.reply(gank_media_list[randint(0,3)])
@commands.Cog.listener('on_message')
async def autoreact(self, message: discord.Message):
if message.guild is not None:
emoji_id = await self.config.guild(message.guild).autoreact_emoji()
if self.check_if_discord_unicode_emoji(emoji_id) is False:
emoji = self.bot.get_emoji(emoji_id)
elif self.check_if_discord_unicode_emoji(emoji_id) is True:
emoji = emoji_id
autoreact_target = await self.config.guild(message.guild).autoreact_target()
if autoreact_target == 0:
return
if not message.author.id == autoreact_target:
return
await message.add_reaction(emoji)
@commands.command(name='autoreact')
@commands.command(aliases=["pxc", "pc", "polarisconvert", "tatsutopolaris", "ttp"])
@commands.guild_only()
async def autoreact_list(self, ctx: commands.Context):
"""Checks Autoreact's settings."""
emoji_id = await self.config.guild(ctx.guild).autoreact_emoji()
autoreact_target = await self.config.guild(ctx.guild).autoreact_target()
if self.check_if_discord_unicode_emoji(emoji_id) is True:
emoji = emoji_id
embed = discord.Embed(color=await self.bot.get_embed_color(None), description=f"Autoreact is currently set to target <@{autoreact_target}> ({autoreact_target}).\nAutoreact's emoji is currently set to {emoji}.")
else:
emoji = self.bot.get_emoji(emoji_id)
embed = discord.Embed(color=await self.bot.get_embed_color(None), description=f"Autoreact is currently set to target <@{autoreact_target}> ({autoreact_target}).\nAutoreact's emoji is currently set to {emoji} ({await self.config.guild(ctx.guild).autoreact_emoji()}).")
async def polarisxpconvert(self, ctx, *, tatsu_studs: str):
"""Converts Tatsu Studs to Polaris XP."""
try:
tatsu_studs_int = int(f"{tatsu_studs}".replace(",", ""))
except ValueError:
await ctx.send(content="Please input a number!")
return
math = round((tatsu_studs_int/25)*10)
output_from = f'{tatsu_studs_int:,}'
output_to = f'{math:,}'
embed = discord.Embed(color=await self.bot.get_embed_color(None))
embed.add_field(name="Tatsu Studs", value=f"{output_from}", inline=False)
embed.add_field(name="Polaris XP", value=f"{output_to}", inline=False)
await ctx.send(embed=embed)
autoreact = app_commands.Group(name='autoreact', guild_only=True, description="This group handles the autoreact functionality.")
def check_if_discord_unicode_emoji(self, emoji: str):
emoji_ranges = [
(0x1F600, 0x1F64F), # Emoticons
(0x1F300, 0x1F5FF), # Miscellaneous symbols and pictographs
(0x1F680, 0x1F6FF), # Transport and map symbols
(0x1F700, 0x1F77F), # Alchemical symbols
]
try:
for char in emoji:
code_point = ord(char)
for start, end in emoji_ranges:
if start <= code_point <= end:
return True
except TypeError:
return False
return False
def extract_id(self, input_string):
match = re.search(r'(?<=:)\d+(?=>)', input_string)
if match:
return int(match.group())
return input_string
@autoreact.command(name="emoji")
@app_commands.describe(emoji="Which emoji are you setting Autoreact to use?")
async def autoreact_emoji(self, interaction: discord.Interaction, emoji: str = None):
"""Sets Autoreact's emoji."""
if emoji:
if self.check_if_discord_unicode_emoji(emoji) is True:
await self.config.guild(interaction.guild).autoreactemoji.set(emoji)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Autoreact's emoji has been set to {emoji}.")
await interaction.response.send_message(embed=embed)
else:
emoji_id = self.extract_id(input_string=emoji)
for guild in self.bot.guilds:
emoji_to_find = discord.utils.get(guild.emojis, id=emoji_id)
if emoji_to_find:
emoji_obj = emoji_to_find
break
else:
await interaction.response.send_message(content="You're trying to set the autoreact emoji to an emoji I don't have access to!", ephemeral=True)
return
await self.config.guild(interaction.guild).autoreact_emoji.set(emoji_obj.id)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Autoreact's emoji has been set to {emoji_obj} ({emoji_obj.id}).")
await interaction.response.send_message(embed=embed)
@commands.command()
async def galaxyissues(self, ctx, target: discord.Member = None):
if ctx.me.id == 1070819799254438039:
embed = discord.Embed(title="Issue Reporting & Suggestions", color=await self.bot.get_embed_color(None), description="Have a problem or a suggestion for the Galaxy bot or GalaxyCogs? Read this!")
embed.add_field(name="Bot Issues & Suggestions", value="If you'd like to submit a suggestion or a bug report to the developers of the Galaxy bot, please do so [here](https://github.com/SeaswimmerTheFsh/GalaxyCogs/issues).\n**Please make sure whatever you're suggesting or reporting doesn't have an existing issue! If it does, you can comment on that issue with additional details if necessary.**")
else:
await self.config.guild(interaction.guild).autoreact_emoji.set('💀')
embed=discord.Embed(color=await self.bot.get_embed_color(None), description="Autoreact's emoji has been set to 💀.")
await interaction.response.send_message(embed=embed)
@autoreact.command(name="set")
@app_commands.describe(member="Who are you targetting?")
async def autoreact_set(self, interaction: discord.Interaction, member: discord.Member):
"""Sets Autoreact's target."""
if member:
await self.config.guild(interaction.guild).autoreact_target.set(member.id)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Autoreact has been set to automatically react to {member.mention} ({member.id})'s messages.")
await interaction.response.send_message(embed=embed)
embed = discord.Embed(title="Issue Reporting & Suggestions", color=await self.bot.get_embed_color(None), description="Have a problem or a suggestion for GalaxyCogs? Read this!")
embed.add_field(name="Cog Issues & Suggestions", value="If you'd like to submit a suggestion or a bug report to the developers of GalaxyCogs, please do so [here](https://github.com/SeaswimmerTheFsh/GalaxyCogs/issues).\n**Please make sure whatever you're suggesting or reporting doesn't have an existing issue! If it does, you can comment on that issue with additional details if necessary.**")
if target:
await ctx.send(embed=embed, content=f"{target.mention}")
else:
await interaction.response.send_message(content="That is not a valid argument!", ephemeral=True)
@autoreact.command(name="reset")
async def autoreact_reset(self, interaction: discord.Interaction):
"""Resets Autoreact's target."""
await self.config.guild(interaction.guild).autoreact_target.set(0)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description="Autoreact's target has been reset.")
await interaction.response.send_message(embed=embed)
await ctx.send(embed=embed)
@commands.command()
async def unix(self, ctx: commands.Context):
async def lwaccess(self, ctx):
"""You shouldn't be able to see this!"""
role = ctx.guild.get_role(1083210988888784996)
if role in ctx.author.roles:
await ctx.author.remove_roles(role, reason="Requested through -lwaccess")
await ctx.send(content="Higher Access role removed.")
else:
await ctx.author.add_roles(role, reason="Requested through -lwaccess")
await ctx.send(content="Higher Access role added.")
@commands.Cog.listener('on_message')
async def cocoreact(self, message):
emoji = self.bot.get_emoji(await self.config.guild(message.guild).cocoemoji())
cocotarget = await self.config.guild(message.guild).cocotarget()
if cocotarget == 0:
return
if not message.author.id == cocotarget:
return
await message.add_reaction(emoji)
@commands.group(autohelp=False, invoke_without_command=True)
@commands.guild_only()
async def coco(self, ctx):
"""Checks who Coco is currently set to."""
emoji = self.bot.get_emoji(await self.config.guild(ctx.guild).cocoemoji())
cocotarget = await self.config.guild(ctx.guild).cocotarget()
embed = discord.Embed(color=await self.bot.get_embed_color(None), description=f"Coco is currently set to <@{cocotarget}> ({cocotarget}).\nCoco's emoji is currently set to {emoji} ({await self.config.guild(ctx.guild).cocoemoji()}).")
await ctx.send(embed=embed)
@coco.command(name="emoji")
@checks.is_owner()
async def coco_emoji_set(self, ctx, emoji: discord.Emoji = None):
"""Sets Coco's emoji."""
if emoji:
await self.config.guild(ctx.guild).cocoemoji.set(emoji.id)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Coco's emoji has been set to {emoji} ({emoji.id}).")
await ctx.send(embed=embed)
else:
await self.config.guild(ctx.guild).cocoemoji.set(1028535684757209118)
emoji = self.bot.get_emoji(1028535684757209118)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Coco's emoji has been set to {emoji} (1028535684757209118).")
await ctx.send(embed=embed)
@coco.command(name="set")
@checks.is_owner()
async def coco_set(self, ctx, member: discord.Member):
"""Sets Coco's target."""
if member:
await self.config.guild(ctx.guild).cocotarget.set(member.id)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Coco has been set to {member.mention} ({member.id}).")
await ctx.send(embed=embed)
else:
await ctx.send(content="That is not a valid argument!")
@coco.command(name="reset")
@checks.is_owner()
async def coco_reset(self, ctx):
"""Resets Coco's target."""
await self.config.guild(ctx.guild).cocotarget.set(0)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"Coco has been reset.")
await ctx.send(embed=embed)
@commands.command()
async def unix(self, ctx):
"""Posts the current Unix timestamp."""
timestamp = int(datetime.timestamp(datetime.now()))
embed=discord.Embed(title="Current Time", url="https://www.unixtimestamp.com/", color=await self.bot.get_embed_color(None))
embed.add_field(name="Default", value=f"<t:{timestamp}>\n`<t:{timestamp}>`")
embed.add_field(name="Short Time", value=f"<t:{timestamp}:t>\n`<t:{timestamp}:t>`")
embed.add_field(name="Long Time", value=f"<t:{timestamp}:T>\n`<t:{timestamp}:T>`")
embed.add_field(name="Short Date/Time", value=f"<t:{timestamp}:f>\n`<t:{timestamp}:f>`")
embed.add_field(name="Short Date", value=f"<t:{timestamp}:d>\n`<t:{timestamp}:d>`")
embed.add_field(name="Long Date", value=f"<t:{timestamp}:D>\n`<t:{timestamp}:D>`")
embed.add_field(name="Long Date/Time", value=f"<t:{timestamp}:F>\n`<t:{timestamp}:F>`")
embed.add_field(name="Relative Time", value=f"<t:{timestamp}:R>\n`<t:{timestamp}:R>`")
embed=discord.Embed(title="Current Time", color=await self.bot.get_embed_color(None), description=f"<t:{timestamp}>")
embed.set_footer(text=f"{timestamp}")
embed.set_image(url="https://cdn.discordapp.com/attachments/1047347377348030494/1080048421127335956/image.png")
await ctx.send(embed=embed)
await ctx.message.delete()
@commands.group(autohelp=True)
async def insurance(self, ctx: commands.Context):
"""Calculates insurance.
Please only use the value of a ship (from ``/shipinfo``) to calculate insurance and **not** ship cost. Decimals do not work properly with this command, just remove them."""
async def _insurance(self, ship_class: str, value: str):
"""This function does the actual math and configures the embed.
Attributes
-----------
ship_class: Required[:class:`str`]
The class of the ship whose insurance you're checking.
value: Required[:class:`int`]
The value of the ship you're checking. This should be supplied by `/shipinfo`. Not the same as ship cost!"""
cleaned_value = int(''.join(char for char in value if char.isdigit()))
insurance_dict = {
"miner": 0.7,
"freighter": 0.65,
"frigate": 0.6,
"destroyer": 0.55,
"cruiser": 0.5,
"battlecruiser": 0.4,
"battleship": 0.35,
"dreadnought": 0.3,
"carrier": 0.3,
"super_capital": 0.25
}
try:
insurance_dict[f'{ship_class}']
except KeyError as error:
raise ValueError("Received value is not a valid ship class!") from error
if ship_class == "super_capital":
humanized_class = ship_class.replace("_", " ").title()
else:
humanized_class = ship_class.capitalize()
insurance_amount = (f"{round(cleaned_value * insurance_dict[f'{ship_class}']):,}")
value_output = (f'{cleaned_value:,}')
embed = discord.Embed(title="Insurance Payout", color=await self.bot.get_embed_color(None))
embed.add_field(name="Ship Class", value=f"{humanized_class}", inline=False)
embed.add_field(name="Ship Value", value=f"{value_output}", inline=False)
embed.add_field(name="Insurance Amount", value=f"{insurance_amount}", inline=False)
return embed
@insurance.command()
async def miner(self, ctx: commands.Context, value):
"""Calculates insurance for miners. (70%)"""
await ctx.send(embed=await self._insurance('miner', value))
@insurance.command()
async def freighter(self, ctx: commands.Context, value):
"""Calculates insurance for freighters. (65%)"""
await ctx.send(embed=await self._insurance('freighter', value))
@insurance.command()
async def frigate(self, ctx: commands.Context, value):
"""Calculates insurance for frigates. (60%)"""
await ctx.send(embed=await self._insurance('frigate', value))
@insurance.command()
async def destroyer(self, ctx: commands.Context, value):
"""Calculates insurance for destroyers. (55%)"""
await ctx.send(embed=await self._insurance('destroyer', value))
@insurance.command()
async def cruiser(self, ctx: commands.Context, value):
"""Calculates insurance for cruisers. (50%)"""
await ctx.send(embed=await self._insurance('cruiser', value))
@insurance.command()
async def battlecruiser(self, ctx: commands.Context, value):
"""Calculates insurance for battlecruisers. (40%)"""
await ctx.send(embed=await self._insurance('battlecruiser', value))
@insurance.command()
async def battleship(self, ctx: commands.Context, value):
"""Calculates insurance for battleships. (35%)"""
await ctx.send(embed=await self._insurance('battleship', value))
@insurance.command()
async def dreadnought(self, ctx: commands.Context, value):
"""Calculates insurance for dreadnoughts. (30%)"""
await ctx.send(embed=await self._insurance('dreadnought', value))
@insurance.command()
async def carrier(self, ctx: commands.Context, value):
"""Calculates insurance for carriers. (30%)"""
await ctx.send(embed=await self._insurance('carrier', value))
@insurance.command()
async def supercapital(self, ctx: commands.Context, value):
"""Calculates insurance for super capitals. (25%)"""
await ctx.send(embed=await self._insurance('super_capital', value))
@commands.command(aliases=["wh"])
@commands.command()
async def warehouse(self, ctx: commands.Context, lvlfrom: int = 1, lvlto: int = 38):
"""Calculates the total cost to upgrade your warehouse from a level to a level."""
warehouse_levels = {1:0, 2:1000,3:2500,4:4500,5:7500,6:12500,7:20000,8:31500,9:46500,10:65500,11:87500,12:113500,13:143500,14:178500,15:218500,16:263500,17:313500,18:373500,19:443500,20:523500,21:613500,22:713500,23:823500,24:943500,25:1073500,26:1223500,27:1398500,28:1598500,29:1823500,30:2073500,31:2353500, 32:2663500, 33:3003500, 34:3373500, 35:3773500, 36:4193500, 37:4644500, 38:5093500}
@ -271,78 +142,129 @@ class Galaxy(commands.Cog):
await ctx.send(embed=embed)
await ctx.message.delete()
@app_commands.command()
@app_commands.describe(answer='Which answer are you trying to post?')
@app_commands.choices(answer=[
Choice(name='Important Links', value='links'),
Choice(name='DPS Calculations', value='dps'),
Choice(name='Reward Roles', value='reward_roles'),
Choice(name='NPC Intervals', value='npc_intervals'),
Choice(name='Linked Role', value='linked_role'),
Choice(name='RoPro', value='ropro')
])
async def faq(self, interaction: discord.Interaction, answer: Choice[str], member: discord.Member = None):
@commands.group(autohelp=True)
async def faq(self, ctx):
"""Posts answers to frequently asked questions."""
embed = None
embed_secondary = None
if answer.value == 'dps':
embed = discord.Embed(title="DPS Calculations", color=await self.bot.get_embed_color(None), description="The ``/info`` command (and by extention ``/shipinfo`` from Odin) misreports DPS, due to it calculating DPS disregarding the turret's type (kinetic, laser), causing it to assume the target ship is both hulled and has shield simultaneously. It also ignores turret overrides, custom reloads, and custom damage values. If you'd like to check ship stats accurately, you can either use the ``/ship`` command in this channel or you can use the [Galaxy Info Website](https://info.galaxy.casa/ships). Alternatively, to check turret stats, you can use the [Galaxy Info Turrets Page](https://info.galaxy.casa/turrets).")
elif answer.value == 'links':
embed = discord.Embed(title="Important Links", color=await self.bot.get_embed_color(None))
embed.add_field(name="Galaxy", value="[Galaxy Discord](https://discord.com/invite/robloxgalaxy)\n[Galaxy Support](https://discord.com/invite/ShWshkhYhZ)")
embed.add_field(name="Galaxypedia", value="[Galaxypedia Website](https://robloxgalaxy.wiki/wiki/Main_Page)\n[Galaxypedia Discord](https://discord.robloxgalaxy.wiki/)")
elif answer.value == 'npc_intervals':
embed = discord.Embed(title="NPC Spawn Intervals", color=await self.bot.get_embed_color(None), description="*Disclaimer: Spawn times may be different if EventID is active!*")
embed.add_field(name="Every 6.7 Minutes", value="[Dragoon](https://robloxgalaxy.wiki/wiki/Dragoon) *(80% Chance)*")
embed.add_field(name="Every 8.3 Minutes", value="[Swarmer](https://robloxgalaxy.wiki/wiki/Swarmer) *(33% Chance)*")
embed.add_field(name="Every 10 Minutes", value="[Jormungand](https://robloxgalaxy.wiki/wiki/Jormungand) *(75% Chance)*")
embed.add_field(name="Every 12.5 Minutes", value="[Bruiser](https://robloxgalaxy.wiki/wiki/Bruiser) *(50% Chance)*")
embed.add_field(name="Every 16.7 Minutes", value="[Outrider](https://robloxgalaxy.wiki/wiki/Outrider) *(50% Chance)*")
embed.add_field(name="Every 28.3 Minutes", value="[Punisher](https://robloxgalaxy.wiki/wiki/Punisher)")
embed.add_field(name="Every 60 Minutes", value="[X-0](https://robloxgalaxy.wiki/wiki/X-0) *(45% Chance)*\n[Decimator](https://robloxgalaxy.wiki/wiki/Decimator)")
embed.add_field(name="Every 70 Minutes", value="[Galleon](https://robloxgalaxy.wiki/wiki/Galleon)")
embed.add_field(name="Every 120 Minutes", value="[Kodiak](https://robloxgalaxy.wiki/wiki/Kodiak)")
elif answer.value == 'linked_role':
embed = discord.Embed(title="Desktop / Web", color=await self.bot.get_embed_color(None), description="**Step 1:** Open the Server Dropdown menu in the top-left by clicking on the server's name.\n\n**Step 2:** Click the \"*Linked Roles*\" button.\n\n**Step 3:** Click on \"*Linked*.\"\n\n**Step 4:** Click \"*Finish*.\" You're done!\n*Note: You should already be Verified on Bloxlink. If you are not, go to the verification channel to verify.*")
embed.set_thumbnail(url="https://cdn.discordapp.com/attachments/1070838419212738621/1079927564421836930/image.png")
embed_secondary = discord.Embed(title="Mobile", color=await self.bot.get_embed_color(None), description="**Step 1:** Open the Server menu on the top of the channel list by tapping the server's name.\n\n**Step 2:** Scroll down and tap the \"*Linked Roles*\" button.\n\n**Step 3:** Tap on \"*Linked*.\"\n\n**Step 4:** Tap \"*Finish*.\" You're done!\n*Note: You should already be Verified on Bloxlink. If you are not, go to the verification channel to verify.*")
embed_secondary.set_thumbnail(url="https://cdn.discordapp.com/attachments/1047347377348030494/1079930169562771576/Screenshot_20230227_195338_Discord.jpg")
elif answer.value == 'reward_roles':
embed = discord.Embed(title="Reward Roles", color=await self.bot.get_embed_color(None))
embed.add_field(name="Picture Perms", value="Level 6")
embed.add_field(name="Suggestions", value="Level 8")
embed.add_field(name="DJ", value="Level 10")
embed.add_field(name="Reaction Perms", value="Level 20")
embed.add_field(name="External Emoji Perms", value="Level 30")
embed.set_footer(text="Use `-profile` to get your current level.")
elif answer.value == 'ropro':
embed = discord.Embed(title="RoPro", url="https://ropro.io", color=await self.bot.get_embed_color(None), description="""[RoPro](https://ropro.io) is a browser extension that tracks ROBLOX playtime, enhances your profile, and provides other useful utilities. **Please keep in mind that RoPro only tracks playtime from AFTER you install the extension.**""")
content = member.mention if member else None
await interaction.response.send_message(content="> The rigid requirement for bots to compulsorily respond to interactions in Discord, such as slash commands or application commands, is an irksome limitation that curtails the flexibility and natural flow of interactions. This forced response paradigm undermines the very essence of automation and intelligent design that bots were intended to offer. There are instances where silence or lack of response is not only acceptable but also desired, aligning with the nuanced dynamics of human communication. Discord's insistence on a response, even when it serves no purpose, imposes unnecessary complexity and verbosity, creating an environment where superfluous replies dilute the efficiency and elegance of bot-driven interactions. This constraint highlights the importance of granting bot developers the autonomy to determine the most suitable course of action based on context, contributing to a more seamless and user-centric experience within the Discord ecosystem.\n - ChatGPT", ephemeral=True)
response: discord.InteractionMessage = await interaction.original_response()
await response.delete()
if embed_secondary:
await interaction.channel.send(content=content, embeds=[embed, embed_secondary])
else:
await interaction.channel.send(content=content, embed=embed)
# @faq.command(name="polaris_switch")
# @checks.admin()
# async def faq_polaris_switch(self, ctx, member: discord.Member = None):
# """Posts an embed on the switch to the Polaris bot."""
# embed=discord.Embed(title="Polaris FAQ", color=await self.bot.get_embed_color(None), description="As you probably know, we've decided to switch to the Polaris bot for leveling/xp, as opposed to Tatsu.\nThere are many reasons for this, which will be explained below.")
# embed.add_field(name="Problems with Tatsu", value="1: Tatsu does not provide nearly as much configuration potential as Polaris does. An example of this is Polaris' customizable Level Curve.\n\n2: Tatsu does not have channel/role modifiers.\n\n3: Tatsu does not have actual levels, instead it has unconfigurable \"Global XP\", which gives \"Global Levels\". You cannot do anything with Global XP aside from blacklisting channels where people can gain it, like a bot-commands channel or something like that.\n\n4: Tatsu's leaderboard sucks, and only shows the top 10 on the web version.\n\n5: Tatsu has no XP management commands.\n\n6: Tatsu has TONS of bloat/useless commands, making the bot harder to configure.", inline=False)
# embed.add_field(name="Polaris' Features", value="1: Polaris allows you to customize the level curve of your server, and provides presets to make the transition easier.\n\n2: Polaris has XP management commands.\n\n3: Polaris has way more configuration in terms of Reward Roles.\n\n4: Polaris allows you to customize the level-up message shown whenever people achieve the next level.\n\n5: Polaris has both role and channel modifiers.\n\n6: Polaris' leaderboard is excellent, showing the top 1,000 ranked users on the same webpage, and allowing you to see your own stats, progress towards your next reward role, and all 350 levels and your progress towards them.\n\n7: Polaris is **just** a leveling bot. You don't have to deal with any of the bloat of multi-purpose bots like Tatsu or MEE6, you only get what you actually need.", inline=False)
# embed.add_field(name="Conclusion",value="With all of that said, you're probably wondering why we're putting so much effort into transferring peoples' data to the new bot.\n\nWell, Tatsu has been going since 2020, and I don't particularly favor the idea of clearing everyone's XP, especially when people have built up reward roles from Tatsu already, like Picture Perms, Suggestions access, and DJ.\n\nWith all this in mind, I hope this isn't too much of an inconvenience for you all, as I tried to make the process as seamless as possible without having to update all 10,000 people in the server.", inline=False)
# if member:
# await ctx.channel.send(embed=embed, content=member.mention)
# else:
# await ctx.channel.send(embed=embed)
# await ctx.message.delete()
@faq.command(name="test")
@checks.admin()
async def faq_test(self, ctx, member: discord.Member = None):
"""Testing FAQ"""
embed=discord.Embed(title="Test Embed", color=await self.bot.get_embed_color(None), description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer in faucibus odio, at mollis metus.")
embed.set_footer(text=ctx.author, icon_url=ctx.author.avatar_url_as(format="png", size=512))
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.message.delete()
@faq.command(name="dps")
async def faq_dps(self, ctx, member: discord.Member = None):
"""DPS Calculations/Inaccuracy"""
embed=discord.Embed(title="DPS Calculations", color=await self.bot.get_embed_color(None), description="The ``/info`` command (and by extention ``/shipinfo`` from Odin) misreports DPS, due to it calculating DPS disregarding the turret's type (kinetic, laser), causing it to assume the target ship is both hulled and has shield simultaneously. It also ignores turret overrides, custom reloads, and custom damage values. If you'd like to check ship stats accurately, you can either use the ``/ship`` command in this channel or you can use the [Galaxy Info Website](https://galaxy.wingysam.xyz/ships). Alternatively, to check turret stats, you can use the [Galaxy Info Turrets Page](https://galaxy.wingysam.xyz/turrets).")
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.message.delete()
@faq.command(name="links")
async def faq_links(self, ctx, member: discord.Member = None):
"""Posts important links, primarily invite links."""
embed=discord.Embed(title="Important Links", color=await self.bot.get_embed_color(None))
embed.add_field(name="Galaxy", value="[Galaxy Discord](https://discord.com/invite/robloxgalaxy)\n[Galaxy Support](https://discord.com/invite/ShWshkhYhZ)")
embed.add_field(name="Galaxypedia", value="[Galaxypedia Website](https://robloxgalaxy.wiki/wiki/Main_Page)\n[Galaxypedia Discord](https://discord.robloxgalaxy.wiki/)")
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.message.delete()
@faq.command(name="ropro")
async def faq_ropro(self, ctx, member: discord.Member = None):
"""Posts a link to RoPro"""
embed=discord.Embed(title="RoPro", url="https://ropro.io", color=await self.bot.get_embed_color(None), description="""[RoPro](https://ropro.io) is a browser extension that tracks ROBLOX playtime, enhances your profile, and provides other useful utilities. **Please keep in mind that RoPro only tracks playtime from AFTER you install the extension.**""")
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.message.delete()
@faq.command(name="polaris_ranks")
async def faq_polaris_ranks(self, ctx, member: discord.Member = None):
"""Lists required levels for certain roles."""
embed=discord.Embed(title="Polaris Ranks", color=await self.bot.get_embed_color(None))
embed.add_field(name="Picture Perms", value="Level 7", inline=False)
embed.add_field(name="Suggestions", value="Level 9", inline=False)
embed.add_field(name="DJ", value="Level 11", inline=False)
embed.add_field(name="Reaction Perms", value="Level 30", inline=False)
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.message.delete()
@faq.command(name="polaris_switch")
@checks.admin()
async def faq_polaris_switch(self, ctx, member: discord.Member = None):
"""Posts an embed on the switch to the Polaris bot."""
embed=discord.Embed(title="Polaris FAQ", color=await self.bot.get_embed_color(None), description="As you probably know, we've decided to switch to the Polaris bot for leveling/xp, as opposed to Tatsu.\nThere are many reasons for this, which will be explained below.")
embed.add_field(name="Problems with Tatsu", value="1: Tatsu does not provide nearly as much configuration potential as Polaris does. An example of this is Polaris' customizable Level Curve.\n\n2: Tatsu does not have channel/role modifiers.\n\n3: Tatsu does not have actual levels, instead it has unconfigurable \"Global XP\", which gives \"Global Levels\". You cannot do anything with Global XP aside from blacklisting channels where people can gain it, like a bot-commands channel or something like that.\n\n4: Tatsu's leaderboard sucks, and only shows the top 10 on the web version.\n\n5: Tatsu has no XP management commands.\n\n6: Tatsu has TONS of bloat/useless commands, making the bot harder to configure.", inline=False)
embed.add_field(name="Polaris' Features", value="1: Polaris allows you to customize the level curve of your server, and provides presets to make the transition easier.\n\n2: Polaris has XP management commands.\n\n3: Polaris has way more configuration in terms of Reward Roles.\n\n4: Polaris allows you to customize the level-up message shown whenever people achieve the next level.\n\n5: Polaris has both role and channel modifiers.\n\n6: Polaris' leaderboard is excellent, showing the top 1,000 ranked users on the same webpage, and allowing you to see your own stats, progress towards your next reward role, and all 350 levels and your progress towards them.\n\n7: Polaris is **just** a leveling bot. You don't have to deal with any of the bloat of multi-purpose bots like Tatsu or MEE6, you only get what you actually need.", inline=False)
embed.add_field(name="Conclusion",value="With all of that said, you're probably wondering why we're putting so much effort into transferring peoples' data to the new bot.\n\nWell, Tatsu has been going since 2020, and I don't particularly favor the idea of clearing everyone's XP, especially when people have built up reward roles from Tatsu already, like Picture Perms, Suggestions access, and DJ.\n\nWith all this in mind, I hope this isn't too much of an inconvenience for you all, as I tried to make the process as seamless as possible without having to update all 10,000 people in the server.", inline=False)
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.message.delete()
@faq.command(name="npc_intervals")
async def faq_npc_intervals(self, ctx, member: discord.Member = None):
"""Posts an embed containing NPC spawn intervals."""
embed=discord.Embed(title="NPC Spawn Intervals", color=await self.bot.get_embed_color(None), description="*Disclaimer: Spawn times may be different if EventID is active!*")
embed.add_field(name="Every 6.7 Minutes", value="[Dragoon](https://robloxgalaxy.wiki/wiki/Dragoon) *(80% Chance)*")
embed.add_field(name="Every 8.4 Minutes", value="[Swarmer](https://robloxgalaxy.wiki/wiki/Swarmer) *(33% Chance)*")
embed.add_field(name="Every 10 Minutes", value="[Jormungand](https://robloxgalaxy.wiki/wiki/Jormungand) *(75% Chance)*")
embed.add_field(name="Every 12.5 Minutes", value="[Bruiser](https://robloxgalaxy.wiki/wiki/Bruiser) *(50% Chance)*")
embed.add_field(name="Every 16.7 Minutes", value="[Outrider](https://robloxgalaxy.wiki/wiki/Outrider) *(50% Chance)*")
embed.add_field(name="Every 28.5 Minutes", value="[Punisher](https://robloxgalaxy.wiki/wiki/Punisher)")
embed.add_field(name="Every 60 Minutes", value="[X-0](https://robloxgalaxy.wiki/wiki/X-0) *(45% Chance)*\n[Decimator](https://robloxgalaxy.wiki/wiki/Decimator)")
embed.add_field(name="Every 70 Minutes", value="[Galleon](https://robloxgalaxy.wiki/wiki/Galleon)")
embed.add_field(name="Every 120 Minutes", value="[Kodiak](https://robloxgalaxy.wiki/wiki/Kodiak)")
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.message.delete()
@faq.command(name="linked_role")
async def faq_linked_role(self, ctx, member: discord.Member = None):
"""Posts an embed containing FAQ about Linked Role."""
color=await self.bot.get_embed_color(None)
embed=discord.Embed(title="Linked Role", color=color, description="**Before reading this, please make sure your Discord client is updated! On Mobile, you can do this by going to your app store of choice and updating Discord manually. On the desktop app you can do this by clicking the green update button in the top right.**")
embed_desktop=discord.Embed(title="Desktop / Web", color=color, description="**Step 1:** Open the Server Dropdown menu in the top-left by clicking on the server's name.\n\n**Step 2:** Click the \"*Linked Roles*\" button.\n\n**Step 3:** Click on \"*Linked*.\"\n\n**Step 4:** Click \"*Finish*.\" You're done!\n*Note: You should already be Verified on Bloxlink. If you are not, go to the verification channel to verify.*")
embed_desktop.set_thumbnail(url="https://cdn.discordapp.com/attachments/1070838419212738621/1079927564421836930/image.png")
embed_mobile=discord.Embed(title="Mobile", color=color, description="**Step 1:** Open the Server menu on the top of the channel list by tapping the server's name.\n\n**Step 2:** Scroll down and tap the \"*Linked Roles*\" button.\n\n**Step 3:** Tap on \"*Linked*.\"\n\n**Step 4:** Tap \"*Finish*.\" You're done!\n*Note: You should already be Verified on Bloxlink. If you are not, go to the verification channel to verify.*")
embed_mobile.set_thumbnail(url="https://cdn.discordapp.com/attachments/1047347377348030494/1079930169562771576/Screenshot_20230227_195338_Discord.jpg")
if member:
await ctx.channel.send(embed=embed, content=member.mention)
else:
await ctx.channel.send(embed=embed)
await ctx.channel.send(embed=embed_desktop)
await ctx.channel.send(embed=embed_mobile)
await ctx.message.delete()
@warehouse.error
@unix.error
async def faq_handler(self, error):
@faq_test.error
@faq_linked_role.error
@faq_npc_intervals.error
@faq_links.error
@faq_dps.error
@faq_ropro.error
@faq_polaris_ranks.error
@faq_polaris_switch.error
async def faq_handler(self, ctx, error):
"""Error Handler for Galaxy."""
if isinstance(error, discord.NotFound):
return
return

View file

@ -1,10 +1,8 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing Galaxy!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"author" : ["SeaswimmerTheFsh"],
"install_msg" : "Thank you for installing Galaxy!\nYou can find the source code of this cog here: https://github.com/SeaswimmerTheFsh/GalaxyCogs",
"name" : "Galaxy",
"short" : "Custom cog intended for use on the Galaxy discord server.",
"description" : "Custom cog intended for use on the Galaxy discord server.",
"end_user_data_statement" : "This cog does not store any End User Data.",
"hidden": true,
"disabled": false
"end_user_data_statement" : "This cog does not store any End User Data."
}

0
galaxy/temp.py Normal file
View file

View file

@ -1,8 +1,8 @@
{
"author": [
"cswimr, yname, meelyman"
"SeaswimmerTheFsh, yname, meelyman"
],
"install_msg": "Thanks for installing my repo!\n\nIf you have any issues with any of the cogs, please create an issue here: https://coastalcommits.com/cswimr/GalaxyCogs/issues.",
"install_msg": "Thanks for installing my repo!\n\nIf you have any issues with any of the cogs, please create an issue here: https://github.com/SeaswimmerTheFsh/GalaxyCogs/issues.",
"name": "Galaxy",
"short": "Cogs intended for use on the Galaxy discord server.",
"description": "Custom cogs/cog modifications intended for the Galaxy discord server."

View file

@ -1,5 +1,5 @@
from .info import Info
async def setup(bot):
await bot.add_cog(Info(bot))
def setup(bot):
bot.add_cog(Info(bot))

View file

@ -1,10 +1,9 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing Info!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"author" : ["SeaswimmerTheFsh"],
"install_msg" : "Thank you for installing Info!\nYou can find the source code of this cog here: https://github.com/SeaswimmerTheFsh/GalaxyCogs",
"name" : "Info",
"short" : "Provides information on Discord objects.",
"description" : "Provides information on Discord objects. Most of this code is shamelessly ripped from <https://github.com/Cog-Creators/Red-DiscordBot/tree/V3/develop/redbot/cogs>.",
"end_user_data_statement" : "This cog does not store any End User Data.",
"hidden": true,
"disabled": false
"end_user_data_statement" : "This cog does not store any End User Data."
}

View file

@ -1,13 +1,19 @@
import re
from datetime import datetime
import discord
from redbot.core import Config, app_commands, commands
from redbot.core import commands, checks, Config
from redbot.core.bot import Red
from redbot.core.i18n import Translator, cog_i18n
from redbot.core.utils.chat_formatting import (bold, humanize_number,
humanize_timedelta)
import re
from redbot.core.utils.chat_formatting import (
bold,
humanize_number,
humanize_timedelta,
)
from redbot.core.utils.common_filters import (
escape_spoilers_and_mass_mentions, filter_invites)
filter_invites,
escape_spoilers_and_mass_mentions
)
_ = T_ = Translator("General", __file__)
@ -28,14 +34,14 @@ class Info(commands.Cog):
self.config.register_user(**self.default_user_settings)
self.cache: dict = {}
async def red_delete_data_for_user(self):
async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete."""
return
@commands.command()
@commands.guild_only()
@commands.bot_has_permissions(embed_links=True)
async def serverinfo(self, ctx: commands.Context, details: bool = False):
async def serverinfo(self, ctx, details: bool = False):
"""
Show server information.
@ -73,8 +79,8 @@ class Info(commands.Cog):
)
)
if guild.icon:
data.set_author(name=guild.name, icon_url=str(guild.icon.replace(format='png')))
data.set_thumbnail(url=str(guild.icon.replace(format='png')))
data.set_author(name=guild.name, icon_url=str(guild.icon_url_as(format='png')))
data.set_thumbnail(url=str(guild.icon_url_as(format='png')))
else:
data.set_author(name=guild.name)
else:
@ -82,16 +88,16 @@ class Info(commands.Cog):
def _size(num: int):
for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
if abs(num) < 1024.0:
return f"{num:.1f}{unit}"
return "{0:.1f}{1}".format(num, unit)
num /= 1024.0
return f"{num:.1f}YB"
return "{0:.1f}{1}".format(num, "YB")
def _bitsize(num: int):
for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]:
if abs(num) < 1000.0:
return f"{num:.1f}{unit}"
return "{0:.1f}{1}".format(num, unit)
num /= 1000.0
return f"{num:.1f}YB"
return "{0:.1f}{1}".format(num, "YB")
shard_info = (
_("\nShard ID: **{shard_id}/{shard_count}**").format(
@ -123,7 +129,7 @@ class Info(commands.Cog):
for emoji, value in online_stats.items():
try:
num = len([m for m in guild.members if value(m)])
except Exception as error: # pylint: disable=broad-exception-caught
except Exception as error:
print(error)
continue
else:
@ -167,7 +173,7 @@ class Info(commands.Cog):
name=guild.name
)
if guild.icon:
data.set_thumbnail(url=str(guild.icon.url))
data.set_thumbnail(url=str(guild.icon_url))
data.add_field(name=_("Members:"), value=member_msg)
data.add_field(
name=_("Channels:"),
@ -254,7 +260,7 @@ class Info(commands.Cog):
)
data.add_field(name=_("Nitro Boost:"), value=nitro_boost)
if guild.splash:
data.set_image(url=str(guild.splash.replace(format='png')))
data.set_image(url=str(guild.splash_url_as(format='png')))
data.set_footer(text=joined_on)
await ctx.send(embed=data)
@ -267,7 +273,7 @@ class Info(commands.Cog):
c_status = None
if not a.name and not a.emoji:
return None, discord.ActivityType.custom
if a.name and a.emoji:
elif a.name and a.emoji:
c_status = _("Custom: {emoji} {name}").format(emoji=a.emoji, name=a.name)
elif a.emoji:
c_status = _("Custom: {emoji}").format(emoji=a.emoji)
@ -341,7 +347,7 @@ class Info(commands.Cog):
self.handle_watching(user),
self.handle_competing(user),
]:
status_string = a
status_string, status_type = a
if status_string is None:
continue
string += f"{status_string}\n"
@ -359,7 +365,7 @@ class Info(commands.Cog):
@commands.command()
@commands.guild_only()
@commands.bot_has_permissions(embed_links=True)
async def userinfo(self, ctx: commands.Context, *, member: discord.Member = None):
async def userinfo(self, ctx, *, member: discord.Member = None):
"""Show information about a member.
This includes fields for status, discord join date, server
join date, voice state and previous names/nicknames.
@ -471,54 +477,25 @@ class Info(commands.Cog):
if voice_state and voice_state.channel:
data.add_field(
name=_("Current voice channel"),
value=f"{voice_state.channel.mention} ID: {voice_state.channel.id}",
value="{0.mention} ID: {0.id}".format(voice_state.channel),
inline=False,
)
data.set_footer(text=_(f"Member #{member_number} | User ID: {member.id}"))
data.set_footer(text=_("Member #{} | User ID: {}").format(member_number, member.id))
if member.discriminator == "0":
name = str(member.name)
else:
name = str(member)
name = str(member)
name = " ~ ".join((name, member.nick)) if member.nick else name
name = filter_invites(name)
avatar = member.avatar.replace(format='png')
avatar = member.avatar_url_as(format='png')
data.set_author(name=f"{statusemoji} {name}", url=avatar)
data.set_thumbnail(url=avatar)
await ctx.send(embed=data)
async def fetch_twemoji(self, unicode_emoji):
base_url = "https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/72x72/"
emoji_codepoint = "-".join([hex(ord(char))[2:] for char in unicode_emoji])
segments = emoji_codepoint.split("-")
valid_segments = [seg for seg in segments if len(seg) >= 4]
emoji_url = f"{base_url}{valid_segments[0]}.png"
return emoji_url
@app_commands.command()
@app_commands.guild_only()
async def roleinfo(self, interaction: discord.Interaction, role: discord.Role, list_permissions: bool = False):
"""Gives information on a given role.
Parameters
-----------
role: discord.Role
The role you're checking
list_permissions: bool
Whether or not to list permissions. Ignored if the role has Administrator.
"""
try:
icon = role.display_icon
if isinstance(icon, discord.Asset):
icon_url = icon.url
elif isinstance(icon, str):
icon_url = await self.fetch_twemoji(unicode_emoji=icon)
else:
icon_url = None
except: # pylint: disable=bare-except
icon_url = None
@commands.command()
@commands.guild_only()
async def roleinfo(self, ctx, role: discord.Role):
"""Gives information on a specific role."""
permissions = role.permissions
if role.color.value == 0:
colorint = 10070709
@ -528,22 +505,9 @@ class Info(commands.Cog):
color = re.sub('#',"",str(role.color))
colorcodelink = f"https://www.color-hex.com/color/{color}"
timestamp = int(datetime.timestamp(role.created_at))
if role.managed is True:
managed_status = "True"
if role.is_premium_subscriber() is True:
managed_status += "\n**Management Type:** Nitro Booster"
if role.is_bot_managed() is True:
managed_status += "\n**Management Type:** Managed Bot Role"
if role.tags.is_guild_connection() is True:
managed_status +="\n**Management Type:** Guild Connection"
if role.tags.is_available_for_purchase() is True:
managed_status +="\n**Management Type:** Subscription"
if permissions.administrator:
embed = discord.Embed(title=f"{role.name}", color=colorint, description=f"**ID:** {role.id}\n**Mention:** {role.mention}\n**Creation Date:** <t:{timestamp}>\n**Color:** [#{color}]({colorcodelink})\n**Hoisted:** {role.hoist}\n**Position:** {role.position}\n**Managed:** {role.managed}\n**Mentionable:** {role.mentionable}\n**Administrator:** {role.permissions.administrator}")
else:
managed_status = "False"
description = f"**ID:** {role.id}\n**Mention:** {role.mention}\n**Creation Date:** <t:{timestamp}>\n**Color:** [#{color}]({colorcodelink})\n**Hoisted:** {role.hoist}\n**Position:** {role.position}\n**Managed:** {managed_status}\n**Mentionable:** {role.mentionable}\n**Administrator:** {permissions.administrator}"
embed = discord.Embed(title=f"{role.name}", color=colorint, description=description)
if icon_url:
embed.set_thumbnail(url=icon_url)
if permissions.administrator is False and list_permissions is True:
embed.add_field(name="Permissions", value=f"**Manage Server:** {permissions.manage_guild}\n**Manage Webhooks:** {permissions.manage_webhooks}\n**Manage Channels:** {permissions.manage_channels}\n**Manage Roles:** {permissions.manage_roles}\n**Create Expressions:** {permissions.create_expressions}\n**Manage Events:** {permissions.manage_events}\n**Manage Messages:** {permissions.manage_messages}\n**Manage Nicknames:** {permissions.manage_nicknames}\n**Mention @everyone**: {permissions.mention_everyone}\n**Ban Members:** {permissions.ban_members}\n**Kick Members:** {permissions.kick_members}\n**Timeout Members:** {permissions.moderate_members}\n**View Audit Log:** {permissions.view_audit_log}")
await interaction.response.send_message(embed=embed, ephemeral=True)
embed = discord.Embed(title=f"{role.name}", color=colorint, description=f"**ID:** {role.id}\n**Mention:** {role.mention}\n**Creation Date:** <t:{timestamp}>\n**Color:** [#{color}]({colorcodelink})\n**Hoisted:** {role.hoist}\n**Position:** {role.position}\n**Managed:** {role.managed}\n**Mentionable:** {role.mentionable}\n**Administrator:** {role.permissions.administrator}")
embed.add_field(name="Permissions", value=f"**Manage Server:** {permissions.manage_guild}\n**Manage Webhooks:** {permissions.manage_webhooks}\n**Manage Channels:** {permissions.manage_channels}\n**Manage Roles:** {permissions.manage_roles}\n**Manage Emojis:** {permissions.manage_emojis}\n**Manage Messages:** {permissions.manage_messages}\n**Manage Nicknames:** {permissions.manage_nicknames}\n**Mention @everyone**: {permissions.mention_everyone}\n**Ban Members:** {permissions.ban_members}\n**Kick Members:** {permissions.kick_members}")
await ctx.send(embed=embed)

View file

@ -1,5 +0,0 @@
from .issues import Issues
async def setup(bot):
await bot.add_cog(Issues(bot))

View file

@ -1,10 +0,0 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing Issues!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"name" : "Issues",
"short" : "This cog allows you to create Gitea issues through a Discord modal.",
"description" : "This cog allows you to create Gitea issues through a Discord modal.",
"end_user_data_statement" : "This cog does not store any End User Data.",
"hidden": true,
"disabled": false
}

View file

@ -1,100 +0,0 @@
import discord
from redbot.core import Config, app_commands, checks, commands
from . import modals
class Issues(commands.Cog):
"""This cog allows you to create Gitea issues through a Discord modal.
Developed by cswimr."""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=4285273314713, force_registration=True)
self.config.register_global(
request_channel = None,
gitea_root_url = None,
gitea_repository_owner = None,
gitea_repository = None,
gitea_token = None
)
@commands.command()
@checks.is_owner()
async def issuesconfig(self, ctx: commands.Context, channel: discord.TextChannel = None):
if channel:
await self.config.request_channel.set(channel.id)
await ctx.send(content=f"Channel set to {channel.mention}.\nRun this command again without a channel argument to configure the other settings.")
else:
await ctx.channel.send(content="Click the button below to configure the cog.", view=self.IssueConfigurationButton(self.config, ctx))
@app_commands.command()
async def issues(self, interaction: discord.Interaction):
"""Found a bug or have a suggestion for the Galaxy bot? Use this command."""
color = await self.bot.get_embed_color(None)
embed = discord.Embed(title="Issue Reporting & Suggestions", color=await self.bot.get_embed_color(None), description="Have a problem or a suggestion for the Galaxy bot or GalaxyCogs? Read this!")
embed.add_field(name="Bot Issues & Suggestions", value="If you'd like to submit a suggestion or a bug report to the developers of the Galaxy bot, please do so with the buttons below or by going [here](https://coastalcommits.com/cswimr/GalaxyCogs/issues/new/choose).\n**Please make sure whatever you're suggesting or reporting doesn't have an existing issue! If it does, you can comment on that issue with additional details if necessary.**")
embed.add_field(name="Cog Issues & Suggestions", value="If you'd like to submit a suggestion or a bug report to the developers of GalaxyCogs, please do so with the buttons below or by going [here](https://coastalcommits.com/cswimr/GalaxyCogs/issues/new/choose).\n**Please make sure whatever you're suggesting or reporting doesn't have an existing issue! If it does, you can comment on that issue with additional details if necessary.**")
await interaction.response.send_message(embed=embed, view=self.IssueButtons(color, self, interaction), ephemeral=True)
async def submit_issue_request(self, interaction: discord.Interaction, original_interaction: discord.Interaction, embed: discord.Embed):
channel = self.bot.get_channel(await self.config.request_channel())
if channel is None:
await original_interaction.edit_original_response(content="Command cancelled.", view=None)
await interaction.response.send_message(content="The cog is misconfigured, please report this error.", ephemeral=True)
try:
message = await channel.send(content=".")
await message.edit(content="", embed=embed, view=self.IssueResponseButtons(channel, message.id, interaction.user))
await original_interaction.edit_original_response(content="Issue request sent!", embed=embed, view=None)
await interaction.response.defer()
except (discord.HTTPException, discord.Forbidden) as error:
await original_interaction.edit_original_response(content="Command cancelled.", view=None)
await interaction.response.send_message(content=f"The cog is misconfigured, please report this error.\n```{error}```", ephemeral=True)
class IssueButtons(discord.ui.View):
def __init__(self, color, cog_instance, original_interaction):
super().__init__()
self.color = color
self.cog_instance = cog_instance
self.original_interaction = original_interaction
@discord.ui.button(label="Bot Bug", style=discord.ButtonStyle.danger)
async def issue_button_bot_bug(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(modals.BotBugModal(self.color, self.cog_instance, self.original_interaction))
@discord.ui.button(label="Cog Bug", style=discord.ButtonStyle.danger)
async def issue_button_cog_bug(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(modals.CogBugModal(self.color, self.cog_instance, self.original_interaction))
@discord.ui.button(label="Bot Suggestion", style=discord.ButtonStyle.blurple)
async def issue_button_bot_suggestion(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(modals.BotSuggestionModal(self.color, self.cog_instance, self.original_interaction))
@discord.ui.button(label="Cog Suggestion", style=discord.ButtonStyle.blurple)
async def issue_button_cog_suggestion(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(modals.CogSuggestionModal(self.color, self.cog_instance, self.original_interaction))
class IssueConfigurationButton(discord.ui.View):
def __init__(self, config, ctx):
super().__init__()
self.config = config
self.ctx = ctx
@discord.ui.button(label="Change Configuration", style=discord.ButtonStyle.blurple, row=0)
async def issue_configuration_button(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(modals.IssuesConfigurationModal(self.config, self.ctx))
class IssueResponseButtons(discord.ui.View):
def __init__(self, channel, message_id, user):
super().__init__()
self.channel = channel
self.message_id = message_id
self.user = user
@discord.ui.button(label="Approve", style=discord.ButtonStyle.green)
async def issue_response_button_approve(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(modals.IssueResponseModal(self.channel, self.message_id, self.user, True))
@discord.ui.button(label="Deny", style=discord.ButtonStyle.danger)
async def issue_response_button_deny(self, interaction: discord.Interaction, button: discord.ui.Button): # pylint: disable=unused-argument
await interaction.response.send_modal(modals.IssueResponseModal(self.channel, self.message_id, self.user, False))

View file

@ -1,382 +0,0 @@
import aiohttp
import discord
from redbot.core import Config
#
# Misc. functions
#
def construct_embed(interaction: discord.Interaction, fields: list[discord.Embed.fields], color: str):
embed = discord.Embed(title="Issue Request", color=color)
for item in fields:
title = item.label
value = item.value
if value is not None:
if len(value) > 1024:
words = value.split()
split_value = []
current_part = ""
for word in words:
if len(current_part) + len(word) + 1 <= 1024:
current_part += word + " "
else:
split_value.append(current_part.strip())
current_part = word + " "
if current_part:
split_value.append(current_part.strip())
for i, part in enumerate(split_value):
embed.add_field(
name=title if i == 0 else "\u200b", value=part, inline=False
)
else:
embed.add_field(name=title, value=value, inline=False)
if interaction.user.discriminator == "0":
username = interaction.user.name
else:
username = f"{interaction.user.name}#{interaction.user.discriminator}"
embed.set_footer(
text=f"Submitted by {username} ({interaction.user.id})",
icon_url=interaction.user.display_avatar.url,
)
return embed
#
# Modals for the core '/issues' command.
#
class BotBugModal(discord.ui.Modal, title="Creating issue..."):
def __init__(self, color, cog_instance, original_interaction):
super().__init__()
self.color = color
self.cog_instance = cog_instance
self.original_interaction = original_interaction
bug_description = discord.ui.TextInput(
label="Describe the bug",
placeholder="A clear and concise description of what the bug is.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
reproduction_steps = discord.ui.TextInput(
label="To Reproduce",
placeholder="What caused the bug?",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
expected_behavior = discord.ui.TextInput(
label="Expected Behavior",
placeholder="A clear and concise description of what you expected to happen.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
additional_context = discord.ui.TextInput(
label="Additional Context",
placeholder="Add any other context about the problem here.",
style=discord.TextStyle.paragraph,
required=False,
max_length=2048
)
async def on_submit(self, interaction: discord.Interaction):
fields = [self.bug_description, self.reproduction_steps, self.expected_behavior, self.additional_context]
embed = construct_embed(interaction, fields, self.color)
embed.set_author(name="Bot Bug Report")
await self.cog_instance.submit_issue_request(interaction=interaction, original_interaction=self.original_interaction, embed=embed)
class CogBugModal(discord.ui.Modal, title="Creating issue..."):
def __init__(self, color, cog_instance, original_interaction):
super().__init__()
self.color = color
self.cog_instance = cog_instance
self.original_interaction = original_interaction
cog_name = discord.ui.TextInput(
label="What cog is causing this error?",
placeholder="If unsure, put \"GalaxyCogs\".",
style=discord.TextStyle.short,
required=True,
max_length=50
)
bug_description = discord.ui.TextInput(
label="Describe the bug",
placeholder="A clear and concise description of what the bug is.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
reproduction_steps = discord.ui.TextInput(
label="To Reproduce",
placeholder="What caused the bug?",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
expected_behavior = discord.ui.TextInput(
label="Expected Behavior",
placeholder="A clear and concise description of what you expected to happen.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
additional_context = discord.ui.TextInput(
label="Additional Context",
placeholder="Add any other context about the problem here.",
style=discord.TextStyle.paragraph,
required=False,
max_length=2048
)
async def on_submit(self, interaction: discord.Interaction):
fields = [self.cog_name, self.bug_description, self.reproduction_steps, self.expected_behavior, self.additional_context]
embed = construct_embed(interaction, fields, self.color)
embed.set_author(name="Cog Bug Report")
await self.cog_instance.submit_issue_request(interaction=interaction, original_interaction=self.original_interaction, embed=embed)
class BotSuggestionModal(discord.ui.Modal, title="Creating issue..."):
def __init__(self, color, cog_instance, original_interaction):
super().__init__()
self.color = color
self.cog_instance = cog_instance
self.original_interaction = original_interaction
suggestion_description = discord.ui.TextInput(
label="Describe your suggestion.",
placeholder="A clear and concise description of what your suggestion is.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
alternatives = discord.ui.TextInput(
label="Describe alternatives you've considered.",
placeholder="A clear and concise description of any alternative solutions or features you've cnosidered.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
additional_context = discord.ui.TextInput(
label="Additional Context",
placeholder="Add any other context about your suggestion here.",
style=discord.TextStyle.paragraph,
required=False,
max_length=2048
)
async def on_submit(self, interaction: discord.Interaction):
fields = [self.suggestion_description, self.alternatives, self.additional_context]
embed = construct_embed(interaction, fields, self.color)
embed.set_author(name="Cog Suggestion")
await self.cog_instance.submit_issue_request(interaction=interaction, original_interaction=self.original_interaction, embed=embed)
class CogSuggestionModal(discord.ui.Modal, title="Creating issue..."):
def __init__(self, color, cog_instance, original_interaction):
super().__init__()
self.color = color
self.cog_instance = cog_instance
self.original_interaction = original_interaction
cog_name = discord.ui.TextInput(
label="What cog is your suggestion for?",
placeholder="If unsure, put \"GalaxyCogs\".",
style=discord.TextStyle.short,
required=True,
max_length=50
)
suggestion_description = discord.ui.TextInput(
label="Describe your suggestion.",
placeholder="A clear and concise description of what your suggestion is.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
alternatives = discord.ui.TextInput(
label="Describe alternatives you've considered.",
placeholder="A clear and concise description of any alternative solutions or features you've cnosidered.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
additional_context = discord.ui.TextInput(
label="Additional Context",
placeholder="Add any other context about your suggestion here.",
style=discord.TextStyle.paragraph,
required=False,
max_length=2048
)
async def on_submit(self, interaction: discord.Interaction):
fields = [self.cog_name, self.suggestion_description, self.alternatives, self.additional_context]
embed = construct_embed(interaction, fields, self.color)
embed.set_author(name="Cog Suggestion")
await self.cog_instance.submit_issue_request(interaction=interaction, original_interaction=self.original_interaction, embed=embed)
#
# Response modal
#
class IssueResponseModal(discord.ui.Modal, title="Sending response message..."):
def __init__(self, channel, message_id, user, approved):
super().__init__()
self.channel = channel
self.message_id = message_id
self.user = user
self.approved = approved
self.config = Config.get_conf(None, cog_name="Issues", identifier=4285273314713)
issue_title_input = discord.ui.TextInput(
label="Title",
placeholder="Only use this if you're accepting the issue request.",
style=discord.TextStyle.short,
required=False,
max_length=200,
)
response = discord.ui.TextInput(
label="Response",
placeholder="",
style=discord.TextStyle.paragraph,
required=False,
max_length=1024,
)
async def on_submit(self, interaction: discord.Interaction):
message: discord.Message = await self.channel.fetch_message(self.message_id)
embed = message.embeds[0]
field_values = []
field_names = []
if self.approved:
embed.color = 1226519
embed.title = "Issue Request Approved"
status = "accepted"
else:
embed.color = 15671552
embed.title = "Issue Request Denied"
status = "denied"
await interaction.response.send_message(content=f"Issue request {status}.", ephemeral=True)
if self.response.value != "":
embed.add_field(
name=f"Response from {interaction.user.name}",
value=self.response.value,
inline=False,
)
if self.approved:
for field in embed.fields:
field_names.append(f"**{field.name}**")
field_values.append(field.value)
if self.issue_title_input.value != "":
_issue_title = self.issue_title_input.value
else:
_issue_title = "Automatically generated issue"
if embed.author.name == "Bot Bug Report":
issue_title = f"[BOT BUG] {_issue_title}"
# desired_labels = ["bot", "bug"]
elif embed.author.name == "Bot Suggestion":
issue_title = f"[BOT SUGGESTION] {_issue_title}"
# desired_labels = ["bot", "enhancement"]
elif embed.author.name == "Cog Bug Report":
issue_title = f"[{field_values[0]}] {_issue_title}"
# desired_labels = ["cog", "bug"]
elif embed.author.name == "Cog Suggestion":
issue_title = f"[{field_values[0]}] {_issue_title}"
# desired_labels = ["cog", "enhancement"]
headers = {
"Authorization": f"Bearer {await self.config.gitea_token()}",
"Accept": "application/json",
}
url = f"{await self.config.gitea_root_url()}/api/v1/repos/{await self.config.gitea_repository_owner()}/{await self.config.gitea_repository()}/issues"
issue_body = "\n".join(
[f"{name}\n{value}" for name, value in zip(field_names, field_values)]
)
# async def fetch_labels():
# async with aiohttp.ClientSession(headers=headers) as session:
# async with session.post(url=f"{await self.config.gitea_root_url()}/api/v1/repos/{await self.config.gitea_repository_owner()}/{await self.config.gitea_repository()}/labels") as response:
# label_list = []
# for label in response.json():
# if label["name"] in desired_labels:
# label_list.append(label["id"])
# if label_list is None:
# print("Error! Labels are not properly configured on the target repository.")
# return await label_list
issue_labels = None
if issue_labels is None:
issue_data = {"title": issue_title, "body": issue_body}
else:
issue_data = {"title": issue_title, "body": issue_body, "labels": issue_labels}
async def create_issue():
async with aiohttp.ClientSession(headers=headers) as session:
async with session.post(url, json=issue_data) as response:
return await response.json(), response.status
response_json, status_code = await create_issue()
if status_code == 201:
await interaction.response.send_message(
content=f"Issue request {status}.\n[Issue successfully created.]({response_json.get('html_url')})",
ephemeral=True,
)
embed.url = response_json.get("html_url")
await message.edit(embed=embed, view=None)
await self.user.send(embed=embed)
#
# Configuration modal
#
class IssuesConfigurationModal(discord.ui.Modal, title="Modifying configuration..."):
def __init__(self, config, ctx):
super().__init__()
self.config = config
self.ctx = ctx
gitea_root_url = discord.ui.TextInput(
label="Gitea Root URL",
placeholder="https://try.gitea.io",
style=discord.TextStyle.short,
required=False,
max_length=200
)
gitea_repository_owner = discord.ui.TextInput(
label="Gitea Repository Owner",
placeholder="foo",
style=discord.TextStyle.short,
required=False,
max_length=200
)
gitea_repository = discord.ui.TextInput(
label="Gitea Repository Name",
placeholder="bar",
style=discord.TextStyle.short,
required=False,
max_length=200
)
gitea_token = discord.ui.TextInput(
label="Gitea User Access Token",
placeholder="Generate one from your user settings page.",
style=discord.TextStyle.short,
required=False,
max_length=200
)
async def on_submit(self, interaction: discord.Interaction):
if self.gitea_token.value != "":
await self.config.gitea_token.set(self.gitea_token.value)
if self.gitea_root_url.value != "":
await self.config.gitea_root_url.set(self.gitea_root_url.value)
if self.gitea_repository_owner.value != "":
await self.config.gitea_repository_owner.set(self.gitea_repository_owner.value)
if self.gitea_repository.value != "":
await self.config.gitea_repository.set(self.gitea_repository.value)
await interaction.response.send_message(content="Configuration changed!")

View file

@ -1,5 +1,5 @@
from .podcast import Podcast
async def setup(bot):
await bot.add_cog(Podcast(bot))
def setup(bot):
bot.add_cog(Podcast(bot))

View file

@ -1,10 +1,9 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing Podcast!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"author" : ["SeaswimmerTheFsh"],
"install_msg" : "Thank you for installing Podcast!\nYou can find the source code of this cog here: https://github.com/SeaswimmerTheFsh/GalaxyCogs",
"name" : "Podcast",
"short" : "Provides a questions submission system.",
"description" : "Provies a questions submission system.",
"end_user_data_statement" : "This cog does not store any End User Data.",
"hidden": true,
"disabled": true
"end_user_data_statement" : "This cog does not store any End User Data."
}

View file

@ -1,9 +1,11 @@
from redbot.core import Config, checks, commands
import discord
from datetime import datetime
from redbot.core.bot import Red
from redbot.core import commands, checks, Config, bot
class Podcast(commands.Cog):
"""Provides a questions submission system for podcasts.
Developed by cswimr."""
Developed by SeaswimmerTheFsh."""
def __init__(self, bot):
self.bot = bot
@ -19,19 +21,20 @@ class Podcast(commands.Cog):
)
@commands.command()
async def podcast(self, ctx: commands.Context, question: str):
async def podcast(self, ctx, question: str):
"""Submits a question to the Podcast."""
prefix = await self.bot.get_valid_prefixes()
if await self.config.guild(ctx.guild).global_mode(True):
submission_channel = ctx.bot.get_channel(await self.config.global_submission_channel())
submission_channel = bot.get_channel(await self.config.global_submission_channel())
blacklisted_users = await self.config.global_blacklisted_users()
elif await self.config.guild(ctx.guild).global_mode(False):
submission_channel = ctx.bot.get_channel(await self.config.guild(ctx.guild).submission_channel())
submission_channel = bot.get_channel(await self.config.guild(ctx.guild).submission_channel())
blacklisted_users = await self.config.guild(ctx.guild).blacklisted_users()
else:
return
if ctx.author.id in blacklisted_users:
await ctx.author.send(content=f"You are blacklisted from ``{prefix}podcast``!")
return
else:
await submission_channel.send(content=f"{question}")
await ctx.send(content="Question submitted!")
@ -45,11 +48,11 @@ class Podcast(commands.Cog):
@podcastset.command(name="global")
async def set_global_mode(self, ctx, enabled: bool):
"""Enables or disables global mode."""
if enabled is True:
if enabled == True:
await self.config.guild(ctx.guild).global_mode.set(True)
await ctx.send(content="``global_mode`` has been enabled.")
elif enabled is False:
elif enabled == False:
await self.config.guild(ctx.guild).global_mode.set(False)
await ctx.send(content="``global_mode`` has been disabled.")
else:
await ctx.send(content="Please specify an argument!")
await ctx.send(content="Please specify an argument!")

2023
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,28 +0,0 @@
[tool.poetry]
name = "galaxycogs"
version = "0.1.0"
description = "Custom cogs/cog modifications intended for the Galaxy discord server."
authors = ["Galaxy Discord Management Team"]
license = "MPL 2"
readme = "README.md"
package-mode = false
[tool.poetry.dependencies]
python = ">=3.9,<3.12"
Red-DiscordBot = "^3.5.5"
pytimeparse2 = "^1.7.1"
prisma = "^0.10.0"
mysql-connector-python = "^8.1.0"
humanize = "^4.8.0"
pytube = "^15.0.0"
ruff = "^0.3.6"
[tool.poetry.group.dev]
optional = true
[tool.poetry.group.dev.dependencies]
pylint = "^2.17.5"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View file

@ -1,5 +0,0 @@
from .send import Send
async def setup(bot):
await bot.add_cog(Send(bot))

View file

@ -1,10 +0,0 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing Send!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"name" : "Send",
"short" : "Allows you to send messages as the bot user!",
"description" : "Allows you to send messages as the bot user!.",
"end_user_data_statement" : "This cog does not store any End User Data.",
"hidden": true,
"disabled": false
}

View file

@ -1,66 +0,0 @@
from typing import Union
import discord
from redbot.core import commands, app_commands
class Send(commands.Cog):
"""Allows you to send messages as the bot account."""
def __init__(self, bot):
self.bot = bot
async def send_to_target(self, target: Union[discord.Member, discord.TextChannel], interaction: discord.Interaction, message: str, secondary_message: str = None):
if isinstance(target, discord.Member):
target_type = "member"
elif isinstance(target, discord.TextChannel):
target_type = "textchannel"
try:
await target.send(message)
if secondary_message is not None:
await target.send(secondary_message)
await interaction.response.send_message(content=f"Message sent to {target.mention}!\nMessage contents:\n```{message}```\n```{secondary_message}```", ephemeral=True)
else:
await interaction.response.send_message(content=f"Message sent to {target.mention}!\nMessage contents:\n```{message}```", ephemeral=True)
except (discord.HTTPException, discord.Forbidden):
if target_type == "member":
await interaction.response.send_message(content="That user has their direct messages closed!", ephemeral=True)
elif target_type == "textchannel":
await interaction.response.send_message(content="I cannot access that channel!", ephemeral=True)
class MessageModal(discord.ui.Modal, title="Sending message..."):
def __init__(self, target):
super().__init__()
self.target = target
message = discord.ui.TextInput(
label="Message Content",
placeholder="I'm contacting you about your cars extended warranty...",
style=discord.TextStyle.paragraph,
max_length=1750
)
secondary_message = discord.ui.TextInput(
label="Secondary Message Content",
placeholder="Typically used for images/image links.",
style=discord.TextStyle.short,
required=False,
max_length=200
)
async def on_submit(self, interaction: discord.Interaction):
await Send.send_to_target(self, self.target, interaction, self.message, self.secondary_message)
send = app_commands.Group(name="send", description="Send a message as the bot user!")
@send.command(name="user", description="Sends a direct message to a user.")
async def user(self, interaction: discord.Interaction, member: discord.Member, message: str = None):
"""Sends a direct message to a user."""
if message:
await Send.send_to_target(self, member, interaction, message)
else:
await interaction.response.send_modal(Send.MessageModal(member))
@send.command(name="channel", description="Sends a message to a channel.")
async def channel(self, interaction: discord.Interaction, channel: discord.TextChannel, message: str = None):
"""Sends a message to a channel."""
if message:
await Send.send_to_target(self, channel, interaction, message)
else:
await interaction.response.send_modal(Send.MessageModal(channel))

View file

@ -1,5 +0,0 @@
from .shortmute import Shortmute
async def setup(bot):
await bot.add_cog(Shortmute(bot))

View file

@ -1,12 +0,0 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing Shortmute!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"name" : "Shortmute",
"short" : "Allows staff members to shortmute individuals for up to 30 minutes.",
"description" : "Allows staff members to shortmute individuals for up to 30 minutes, using Discord's Timeouts feature.",
"tags" : ["moderation, mutes, timeouts"],
"end_user_data_statement": "This cog stores no end user data.",
"requirements": ["pytimeparse2"],
"hidden": true,
"disabled": false
}

View file

@ -1,346 +0,0 @@
import discord
from discord import ui
from discord.ext.commands import Bot
from pytimeparse2 import disable_dateutil, parse
from redbot.core import Config, app_commands, commands
class Shortmute(commands.Cog):
"""Allows staff members to shortmute individuals for up to 30 minutes, using Discord's Timeouts feature."""
def __init__(self, bot) -> None:
self.bot = bot
self.config = Config.get_conf(self, identifier=25781647388294, force_registration=True)
self.config.register_guild(
dm = True,
confirm = True,
logging_channels = [],
immune_roles = [],
blacklisted_users = []
)
@app_commands.command()
@app_commands.rename(target='member')
async def shortmute(self, interaction: discord.Interaction, target: discord.Member, duration: int, reason: str, evidence_link: str = None, evidence_image: discord.Attachment = None, skip_confirmation: bool = None):
"""Shortmute someone for up to 30m.
Parameters
-----------
target: discord.Member
The member to shortmute
duration: int
The duration of the shortmute
reason: str
The reason for the shortmute
evidence_link: str = None
An image link to evidence for the shortmute, do not use with evidence_image
evidence_image: discord.Attachment = None
An image file used as evidence for the shortmute, do not use with evidence_link
skip_confirmation: bool = None
This allows you skip the confirmation prompt and immediately shortmute the user.
"""
disable_dateutil()
timedelta = parse(f'{duration} minutes', as_timedelta=True)
if evidence_image and evidence_link:
await interaction.response.send_message(content="You've provided both the `evidence_image` and the `evidence_link` arguments! Please only use one or the other.", ephemeral=True)
return
if evidence_link:
evidence = evidence_link
elif evidence_image:
evidence = str(evidence_image)
else:
evidence = None
if skip_confirmation is None:
skip_confirmation = not bool(await self.config.guild(interaction.guild).confirm())
passed_info = {
"target": target,
"timedelta": timedelta,
"reason": reason,
"interaction": interaction,
"color": await self.bot.get_embed_color(interaction.guild),
"evidence": evidence
}
blacklisted_users_list = await self.config.guild(interaction.guild).blacklisted_users()
for user_id in blacklisted_users_list:
if user_id == interaction.user.id:
await interaction.response.send_message(content="You are blacklisted from `/shortmute`!", ephemeral=True)
return
if target.bot is True:
await interaction.response.send_message(content="You cannot shortmute bots!", ephemeral=True)
return
if interaction.user.guild_permissions.administrator is False:
immune_roles_list = await self.config.guild(interaction.guild).immune_roles()
for role_id in immune_roles_list:
role = interaction.guild.get_role(role_id)
if role in target.roles:
await interaction.response.send_message(content="You're trying to shortmute someone who is immune from shortmuting.", ephemeral=True)
return
if target.guild_permissions.administrator is True:
await interaction.response.send_message(content="You cannot shortmute people with the Administrator permission!", ephemeral=True)
return
if duration in (1, -1):
readable_duration = f"{duration} minute"
else:
readable_duration = f"{duration} minutes"
passed_info.update({
"readable_duration": readable_duration
})
if duration > 30:
await interaction.response.send_message(content=f"{readable_duration} is longer than the 30 minutes you are allowed to shortmute users for.", ephemeral=True)
return
if duration < 1:
await interaction.response.send_message(content=f"Please shortmute the user for longer than {readable_duration}! The maximum duration is 30 minutes.", ephemeral=True)
return
if skip_confirmation is False:
embed = discord.Embed(title="Are you sure?", description=f"**Moderator:** {interaction.user.mention}\n**Target:** {target.mention}\n**Duration:** {readable_duration}\n**Reason:** `{reason}`", color=await self.bot.get_embed_color(interaction.guild))
embed.set_footer(text="/shortmute")
if evidence:
embed.set_image(url=evidence)
await interaction.response.send_message(embed=embed, view=self.ShortmuteButtons(timeout=180, passed_info=passed_info), ephemeral=True)
elif skip_confirmation is True:
edit_embed = discord.Embed(title="Shortmute confirmed!", description=f"**Moderator:** {interaction.user.mention}\n**Target:** {target.mention}\n**Duration:** {readable_duration}\n**Reason:** `{reason}`", color=await self.bot.get_embed_color(interaction.guild))
edit_embed.set_footer(text="/shortmute")
if evidence:
edit_embed.set_image(url=evidence)
message = await interaction.response.send_message(embed=edit_embed, ephemeral=True)
await target.timeout(timedelta, reason=f"User shortmuted for {readable_duration} by {interaction.user.name} ({interaction.user.id}) for: {reason}")
shortmute_msg = await interaction.channel.send(content=f"{target.mention} was shortmuted for {readable_duration} by {interaction.user.mention} for: `{reason}`")
if await self.config.guild(interaction.guild).dm() is True:
dm_embed = discord.Embed(title=f"You've been shortmuted in {interaction.guild.name}!", description=f"**Moderator:** {interaction.user.mention}\n**Target:** {target.mention}\n**Message:** {shortmute_msg.jump_url}\n**Duration:** {readable_duration}\n**Reason:** `{reason}`", color=await self.bot.get_embed_color(interaction.guild))
dm_embed.set_footer(text="/shortmute")
if evidence:
dm_embed.set_image(url=evidence)
try:
await target.send(embed=dm_embed)
except discord.HTTPException:
await message.edit(content="Could not message the target, user most likely has Direct Messages disabled.")
logging_channels_list = await self.config.guild(interaction.guild).logging_channels()
if logging_channels_list:
logging_embed = discord.Embed(title="User Shortmuted", description=f"**Moderator:** {interaction.user.mention} ({interaction.user.id})\n**Target:** {target.mention} ({target.id})\n**Message:** {shortmute_msg.jump_url}\n**Duration:** {readable_duration}\n**Reason:** `{reason}`\n**Confirmation Skipped:** True", color=await self.bot.get_embed_color(interaction.guild))
logging_embed.set_footer(text="/shortmute")
if evidence:
logging_embed.set_image(url=evidence)
for channel_id in logging_channels_list:
channel_obj = interaction.guild.get_channel(channel_id)
await channel_obj.send(embed=logging_embed)
class ShortmuteButtons(ui.View):
def __init__(self, timeout, passed_info: dict):
super().__init__()
self.timeout = timeout
self.passed_info = passed_info
self.config = Config.get_conf(None, cog_name='Shortmute', identifier=25781647388294)
@ui.button(label="Yes", style=discord.ButtonStyle.success)
async def shortmute_button_yes(self, button: ui.Button, interaction: discord.Interaction): # pylint: disable=unused-argument
disable_dateutil()
target: discord.Member = self.passed_info['target']
readable_duration = self.passed_info['readable_duration']
reason: str = self.passed_info['reason']
old_interaction: discord.Interaction = self.passed_info['interaction']
color = self.passed_info['color']
timedelta = self.passed_info['timedelta']
evidence = self.passed_info['evidence']
edit_embed = discord.Embed(title="Shortmute confirmed!", description=f"**Moderator:** {old_interaction.user.mention}\n**Target:** {target.mention}\n**Duration:** {readable_duration}\n**Reason:** `{reason}`", color=color)
if evidence:
edit_embed.set_image(url=evidence)
old_message = await old_interaction.edit_original_response(embed=edit_embed, view=None)
await target.timeout(timedelta, reason=f"User shortmuted for {readable_duration} by {old_interaction.user.name} ({old_interaction.user.id}) for: {reason}")
await old_interaction.channel.send(content=f"{target.mention} was shortmuted for {readable_duration} by {old_interaction.user.mention} for: `{reason}`")
if await self.config.guild(old_interaction.guild).dm() is True:
dm_embed = discord.Embed(title=f"You've been shortmuted in {old_interaction.guild.name}!", description=f"**Moderator:** {old_interaction.user.mention}\n**Target:** {target.mention}\n**Duration:** {readable_duration}\n**Reason:** `{reason}`", color=color)
dm_embed.set_footer(text="/shortmute")
if evidence:
dm_embed.set_image(url=evidence)
try:
await target.send(embed=dm_embed)
except discord.HTTPException:
await old_message.edit(content="Could not message the target, user most likely has Direct Messages disabled.")
logging_channels_list = await self.config.guild(old_interaction.guild).logging_channels()
if logging_channels_list:
logging_embed = discord.Embed(title="User Shortmuted", description=f"**Moderator:** {old_interaction.user.mention} ({old_interaction.user.id})\n**Target:** {target.mention} ({target.id})\n**Duration:** {readable_duration}\n**Reason:** `{reason}`\n**Confirmation Skipped:** False", color=color)
logging_embed.set_footer(text="/shortmute")
if evidence:
logging_embed.set_image(url=evidence)
for channel_id in logging_channels_list:
channel_obj = old_interaction.guild.get_channel(channel_id)
await channel_obj.send(embed=logging_embed)
@ui.button(label="No", style=discord.ButtonStyle.danger)
async def shortmute_button_no(self, button: ui.Button, interaction: discord.Interaction): # pylint: disable=unused-argument
message: discord.Message = await self.passed_info['interaction'].edit_original_response(content="Command cancelled.", view=None, embed=None)
await message.delete(delay=3)
@commands.group(name='shortmuteset', autohelp=True)
@commands.guild_only()
@commands.admin()
async def shortmute_config(self, ctx: commands.Context):
"""Used to configure the /shortmute command."""
@shortmute_config.group(name='channel', invoke_without_command=True, aliases=['channels'])
@commands.guild_only()
@commands.admin()
async def shortmute_config_channel(self, ctx: commands.Context):
"""Manages /shortmute logging."""
current_list = await self.config.guild(ctx.guild).logging_channels()
already_in_list = []
for channel_id in current_list:
channel_obj = ctx.guild.get_channel(channel_id)
if channel_obj:
already_in_list.append(channel_obj.mention)
if already_in_list:
await ctx.send("Channels already in the list:\n" + "\n".join(already_in_list))
else:
await ctx.send("No channels are currently in the logging list.")
@shortmute_config_channel.command(name='add')
@commands.guild_only()
@commands.admin()
async def shortmute_config_channel_add(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Adds a channel to the logging channels list."""
current_list: list = await self.config.guild(ctx.guild).logging_channels()
if channel:
if channel.id in current_list:
await ctx.send("This channel is already in the logging channel list!")
else:
current_list.append(channel.id)
await self.config.guild(ctx.guild).logging_channels.set(current_list)
await ctx.send(f"{channel.mention} has been added to the logging channels list.")
else:
await ctx.send("Please provide a valid channel!")
@shortmute_config_channel.command(name='remove')
@commands.guild_only()
@commands.admin()
async def shortmute_config_channel_remove(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Removes a channel from the logging channels list."""
current_list = await self.config.guild(ctx.guild).logging_channels()
if channel.id in current_list:
current_list.remove(channel.id)
await self.config.guild(ctx.guild).logging_channels.set(current_list)
await ctx.send(f"{channel.mention} has been removed from the logging channels list.")
else:
await ctx.send("Please provide a valid channel that exists in the logging channels list.")
@shortmute_config.group(name='role', invoke_without_command=True, aliases=['roles'])
@commands.guild_only()
@commands.admin()
async def shortmute_config_role(self, ctx: commands.Context):
"""Manages the immune roles list."""
current_list = await self.config.guild(ctx.guild).immune_roles()
already_in_list = []
for role_id in current_list:
role_obj = ctx.guild.get_role(role_id)
if role_obj:
already_in_list.append(role_obj.mention)
if already_in_list:
await ctx.send("Roles already in the immune roles list:\n" + "\n".join(already_in_list), allowed_mentions = discord.AllowedMentions(roles=False))
else:
await ctx.send("No roles are currently in the immune roles list.")
@shortmute_config_role.command(name='add')
@commands.guild_only()
@commands.admin()
async def shortmute_config_role_add(self, ctx: commands.Context, role: discord.Role = None):
"""Adds roles to the immune roles list."""
current_list = await self.config.guild(ctx.guild).immune_roles()
if role:
if role.id in current_list:
await ctx.send("This role is already in the immune roles list!")
else:
current_list.append(role.id)
await self.config.guild(ctx.guild).immune_roles.set(current_list)
await ctx.send(f"{role.mention} has been added to the immune roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
else:
await ctx.send("Please provide a valid role.")
@shortmute_config_role.command(name='remove')
@commands.guild_only()
@commands.admin()
async def shortmute_config_role_remove(self, ctx: commands.Context, role: discord.Role = None):
"""Removes roles from the immune roles list."""
current_list = await self.config.guild(ctx.guild).immune_roles()
if role.id in current_list:
current_list.remove(role.id)
await self.config.guild(ctx.guild).immune_roles.set(current_list)
await ctx.send(f"{role.mention} has been removed from the immune roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
else:
await ctx.send("Please provide a valid role that exists in the immune roles list.")
@shortmute_config.group(name='blacklist', invoke_without_command=True)
@commands.guild_only()
@commands.admin()
async def shortmute_config_blacklist(self, ctx: commands.Context):
"""Manages the blacklist."""
current_list = await self.config.guild(ctx.guild).blacklisted_users()
already_in_list = []
for user_id in current_list:
user_obj = await Bot.fetch_user(user_id) # pylint: disable=no-value-for-parameter
if user_obj:
already_in_list.append(user_obj.mention)
if already_in_list:
await ctx.send("Users already blacklisted:\n" + "\n".join(already_in_list), allowed_mentions = discord.AllowedMentions(users=False))
else:
await ctx.send("No users are currently blacklisted.")
@shortmute_config_blacklist.command(name='add')
@commands.guild_only()
@commands.admin()
async def shortmute_config_blacklist_add(self, ctx: commands.Context, user: discord.User = None):
"""Adds users to the /shortmute blacklist."""
current_list = await self.config.guild(ctx.guild).blacklisted_users()
if user:
if user.id in current_list:
await ctx.send("That user is already in the blacklisted users list!")
else:
current_list.append(user.id)
await self.config.guild(ctx.guild).blacklisted_users.set(current_list)
await ctx.send(f"{user.mention} has been blacklisted from using `/shortmute`.", allowed_mentions = discord.AllowedMentions(users=False))
else:
await ctx.send("Please provide a valid user.")
@shortmute_config_blacklist.command(name='remove')
@commands.guild_only()
@commands.admin()
async def shortmute_config_blacklist_remove(self, ctx: commands.Context, user: discord.User = None):
"""Removes users from the /shortmute blacklist."""
current_list = await self.config.guild(ctx.guild).blacklisted_users()
if user.id in current_list:
current_list.remove(user.id)
await self.config.guild(ctx.guild).blacklisted_users.set(current_list)
await ctx.send(f"{user.mention} has been removed from the `/shortmute` blacklist.", allowed_mentions = discord.AllowedMentions(users=False))
else:
await ctx.send("Please provide a valid user who is blacklisted from `/shortmute`.")
@shortmute_config.command(name='message')
@commands.guild_only()
@commands.admin()
async def shortmute_config_message(self, ctx: commands.Context, enabled: bool = None):
"""Manages if /shortmute Direct Messages its target.
Parameters
------------
enabled: bool (optional)
This parameter, if set, will toggle this setting to either True or False."""
old_value = await self.config.guild(ctx.guild).dm()
if enabled is None:
await ctx.send(content=f"Shortmute Direct Messages are currently {'enabled' if old_value else 'disabled'}!")
else:
await self.config.guild(ctx.guild).dm.set(enabled)
await ctx.send(content=f"Shortmute Direct Message setting changed!\nOld value: `{old_value}`\nNew value: `{enabled}`")
@shortmute_config.command(name='confirmation', aliases=['confirm'])
@commands.guild_only()
@commands.admin()
async def shortmute_config_confirmation(self, ctx: commands.Context, enabled: bool = None):
"""Manages if /shortmute has a confirmation prompt by default.
Parameters
------------
enabled: bool (optional)
This parameter, if set, will toggle this setting to either True or False."""
old_value = await self.config.guild(ctx.guild).confirm()
if enabled is None:
await ctx.send(content=f"Shortmute Confirmations are currently {'enabled' if old_value else 'disabled'} by default!")
else:
await self.config.guild(ctx.guild).confirm.set(enabled)
await ctx.send(content=f"Shortmute Confirmation setting changed!\nOld value: `{old_value}`\nNew value: `{enabled}`")

View file

@ -1,12 +1,5 @@
from .suggestions import Suggestions, approve_context, deny_context
from .suggestions import Suggestions
async def setup(bot):
await bot.add_cog(Suggestions(bot))
bot.tree.add_command(approve_context)
bot.tree.add_command(deny_context)
async def teardown(bot):
# We're removing the commands here to ensure they get unloaded properly when the cog is unloaded.
bot.tree.remove_command("approve_context", type=discord.AppCommandType.message) # pylint: disable=undefined-variable
bot.tree.remove_command("deny_context", type=discord.AppCommandType.message) # pylint: disable=undefined-variable
def setup(bot):
bot.add_cog(Suggestions(bot))

View file

@ -1,11 +1,9 @@
{
"author" : ["cswimr, meelyman"],
"install_msg" : "Thank you for installing Suggestions!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs\nYou can find the original source code from SauriCogs here: <https://github.com/elijabesu/SauriCogs>",
"author" : ["SeaswimmerTheFsh, meelyman"],
"install_msg" : "Thank you for installing Suggestions!\nYou can find the source code of this cog here: https://github.com/SeaswimmerTheFsh/GalaxyCogs\nYou can find the original source code from SauriCogs here: <https://github.com/elijabesu/SauriCogs>",
"name" : "Suggestions",
"short" : "Simple suggestions system.",
"description" : "Per guild suggestions system.",
"tags" : ["suggestions, suggestion, voting"],
"end_user_data_statement": "This cog stores user names, discriminators, and IDs upon sending a suggestion. This data is used solely to display user information in suggestions.",
"hidden": true,
"disabled": false
"end_user_data_statement": "This cog stores user names, discriminators, and IDs upon sending a suggestion. This data is used solely to display user information in suggestions."
}

View file

@ -1,7 +1,10 @@
import re
import typing
import discord
from redbot.core import Config, app_commands, checks, commands
import datetime
import typing
from redbot.core import Config, checks, commands
from redbot.core.utils.chat_formatting import humanize_list
from redbot.core.bot import Red
@ -41,12 +44,7 @@ class Suggestions(commands.Cog):
rtext=None,
)
def check_discrim(self, user: discord.User):
if user.discriminator == "0":
return user.name
return f"{user.name}#{user.discriminator}"
async def red_delete_data_for_user(self, *, requester, user_id: discord.User.id):
async def red_delete_data_for_user(self, *, requester, user_id):
# per guild suggestions
for guild in self.bot.guilds:
for suggestion_id in range(1, await self.config.guild(guild).next_id()):
@ -62,13 +60,11 @@ class Suggestions(commands.Cog):
context = super().format_help_for_context(ctx)
return f"{context}"
@commands.command(name='suggest')
@commands.command()
@commands.guild_only()
@checks.bot_has_permissions(add_reactions=True)
async def suggest(self, ctx: commands.Context, *, suggestion: str):
"""Suggest something."""
if ctx.interaction is True:
await ctx.defer()
suggest_id = await self.config.guild(ctx.guild).suggest_id()
if not suggest_id:
if not await self.config.toggle():
@ -82,9 +78,9 @@ class Suggestions(commands.Cog):
"Uh oh, looks like the Admins haven't added the required channel."
)
embed = discord.Embed(color=await ctx.embed_colour(), description=suggestion)
footer = [f"Suggested by {self.check_discrim(ctx.author)} • ({ctx.author.id})",
ctx.author.display_avatar.url]
author = [f"{ctx.author.display_name}", ctx.author.display_avatar.url]
footer = [f"Suggested by {ctx.author.name}#{ctx.author.discriminator}",
ctx.author.avatar_url]
author = [f"{ctx.author.name}#{ctx.author.discriminator} ({ctx.author.id})", ctx.author.avatar_url]
embed.set_footer(
text=footer[0],
icon_url=footer[1]
@ -135,7 +131,7 @@ class Suggestions(commands.Cog):
reason: typing.Optional[str],
):
"""Approve a suggestion."""
await self._finish_suggestion(ctx, suggestion_id, True, reason)
await self._finish_suggestion(ctx, suggestion_id, True, reason, ctx.author)
@checks.admin()
@commands.command()
@ -149,7 +145,7 @@ class Suggestions(commands.Cog):
reason: typing.Optional[str],
):
"""Deny a suggestion. Reason is optional."""
await self._finish_suggestion(ctx, suggestion_id, False, reason)
await self._finish_suggestion(ctx, suggestion_id, False, reason, ctx.author)
@checks.admin()
@commands.command()
@ -187,8 +183,8 @@ class Suggestions(commands.Cog):
content = old_msg.content
approved = "Approved" if approve else "Denied"
embed.title = f"Suggestion {approved} (#{suggestion_id})"
footer = [f"{approved} by {self.check_discrim(author)} ({author.id})",
author.display_avatar.replace(format="png", size=512)]
footer = [f"{approved} by {author.name}#{author.discriminator} ({author.id}",
author.avatar_url_as(format="png", size=512)]
embed.set_footer(
text=footer[0],
icon_url=footer[1]
@ -234,7 +230,7 @@ class Suggestions(commands.Cog):
"""Set the channel for approved suggestions.
If the channel is not provided, approved suggestions will not be reposted.
This cannot be the same channel as denied suggestions."""
old_channel = ctx.guild.get_channel(await self.config.guild(ctx.guild).approve_id())
if channel:
@ -258,7 +254,7 @@ class Suggestions(commands.Cog):
"""Set the channel for denied suggestions.
If the channel is not provided, denied suggestions will not be reposted.
This cannot be the same channel as approved suggestions."""
old_channel = ctx.guild.get_channel(await self.config.guild(ctx.guild).denied_id())
if channel:
@ -370,7 +366,7 @@ class Suggestions(commands.Cog):
embed = discord.Embed(
colour=await ctx.embed_colour()
)
embed.set_author(name=ctx.guild.name, icon_url=ctx.guild.icon.url)
embed.set_author(name=ctx.guild.name, icon_url=ctx.guild.icon_url)
embed.title = "**Suggestion settings:**"
embed.add_field(name="Suggestions channel:", value=suggest_channel)
@ -393,7 +389,7 @@ class Suggestions(commands.Cog):
await ctx.send(embed=embed)
@commands.Cog.listener()
async def on_reaction_add(self, reaction: discord.Reaction, user: discord.Message):
async def on_reaction_add(self, reaction, user):
message = reaction.message
if user.id == self.bot.user.id:
return
@ -408,7 +404,7 @@ class Suggestions(commands.Cog):
):
await message_reaction.remove(user)
async def _get_results(self, ctx: commands.Context, message: discord.Message):
async def _get_results(self, ctx, message):
up_emoji, down_emoji = await self._get_emojis(ctx)
up_count = 0
down_count = 0
@ -421,7 +417,7 @@ class Suggestions(commands.Cog):
return f"{up_count}x {up_emoji}\n{down_count}x {down_emoji}"
async def _get_emojis(self, ctx: typing.Union[commands.Context, discord.Interaction]):
async def _get_emojis(self, ctx):
up_emoji = self.bot.get_emoji(await self.config.guild(ctx.guild).up_emoji())
if not up_emoji:
up_emoji = "✅"
@ -430,9 +426,8 @@ class Suggestions(commands.Cog):
down_emoji = "❎"
return up_emoji, down_emoji
async def _finish_suggestion(self, ctx: commands.Context, suggestion_id: int, approve: bool, reason: str):
async def _finish_suggestion(self, ctx, suggestion_id, approve, reason, author):
server = ctx.guild.id
author = ctx.author
old_channel = ctx.guild.get_channel(
await self.config.guild(ctx.guild).suggest_id()
)
@ -462,8 +457,8 @@ class Suggestions(commands.Cog):
approved = "Approved" if approve else "Denied"
embed.title = f"Suggestion {approved} (#{suggestion_id})"
footer = [f"{approved} by {self.check_discrim(author)} ({author.id})",
author.display_avatar.replace(format="png", size=512)]
footer = [f"{approved} by {author.name}#{author.discriminator} ({author.id}",
author.avatar_url_as(format="png", size=512)]
embed.set_footer(
text=footer[0],
icon_url=footer[1]
@ -508,163 +503,4 @@ class Suggestions(commands.Cog):
await self.config.custom("SUGGESTION", server, suggestion_id).denied.set(
True
)
await ctx.tick()
async def _interaction_get_results(self, interaction: discord.Interaction, message: discord.Message):
up_emoji, down_emoji = await self._get_emojis(interaction)
up_count = 0
down_count = 0
for reaction in message.reactions:
if reaction.emoji == up_emoji:
up_count = reaction.count - 1 # minus the bot
if reaction.emoji == down_emoji:
down_count = reaction.count - 1 # minus the bot
return f"{up_count}x {up_emoji}\n{down_count}x {down_emoji}"
async def _interaction_finish_suggestion(self, interaction: discord.Interaction, message: discord.Message, approve: bool, reason: str = None):
embed = message.embeds
title = embed[0].title
if not title.startswith("Suggestion #"):
await interaction.response.send_message(content="This message is not a suggestion!", ephemeral=True)
return
numbers = re.findall(r'\d+', title)
suggestion_id = ''.join(numbers)
author = interaction.user
server = interaction.guild.id
old_channel = interaction.guild.get_channel(
await self.config.guild(interaction.guild).suggest_id()
)
if approve:
channel = interaction.guild.get_channel(
await self.config.guild(interaction.guild).approve_id()
)
else:
channel = interaction.guild.get_channel(
await self.config.guild(interaction.guild).denied_id()
)
msg_id = await self.config.custom("SUGGESTION", server, suggestion_id).msg_id()
if (
msg_id != 0
and await self.config.custom("SUGGESTION", server, suggestion_id).finished()
):
return await interaction.response.send_message(content="This suggestion has been finished already.", ephemeral=True)
try:
old_msg = await old_channel.fetch_message(msg_id)
except discord.NotFound:
return await interaction.response.send_message(content="Uh oh, message with this ID doesn't exist.", ephemeral=True)
if not old_msg:
return await interaction.response.send_message(content="Uh oh, message with this ID doesn't exist.", ephemeral=True)
embed = old_msg.embeds[0]
content = old_msg.content
approved = "Approved" if approve else "Denied"
embed.title = f"Suggestion {approved} (#{suggestion_id})"
footer = [f"{approved} by {self.check_discrim(author)} • ({author.id})",
author.display_avatar.replace(format="png", size=512)]
embed.set_footer(
text=footer[0],
icon_url=footer[1]
)
embed.add_field(
name="Results", value=await self._interaction_get_results(interaction, old_msg), inline=False
)
if reason:
embed.add_field(name="Reason", value=reason, inline=False)
await self.config.custom("SUGGESTION", server, suggestion_id).reason.set(
True
)
await self.config.custom("SUGGESTION", server, suggestion_id).rtext.set(
reason
)
if channel:
if not await self.config.guild(interaction.guild).same():
if await self.config.guild(interaction.guild).delete_suggestion():
await old_msg.delete()
nmsg = await channel.send(content=content, embed=embed)
await self.config.custom(
"SUGGESTION", server, suggestion_id
).msg_id.set(nmsg.id)
else:
await old_msg.edit(content=content, embed=embed)
else:
if not await self.config.guild(interaction.guild).same():
if await self.config.guild(interaction.guild).delete_suggestion():
await old_msg.delete()
await self.config.custom(
"SUGGESTION", server, suggestion_id
).msg_id.set(1)
else:
await old_msg.edit(content=content, embed=embed)
await self.config.custom("SUGGESTION", server, suggestion_id).finished.set(True)
if approve:
await self.config.custom("SUGGESTION", server, suggestion_id).approved.set(
True
)
else:
await self.config.custom("SUGGESTION", server, suggestion_id).denied.set(
True
)
return nmsg
# pylint: disable=protected-access
class SuggestionApproveModal(discord.ui.Modal, title="Approving suggestion..."):
def __init__(self, message):
super().__init__()
self.message: discord.Message = message
reason = discord.ui.TextInput(
label="Approval Reason",
placeholder="Why are you approving this suggestion?",
style=discord.TextStyle.paragraph,
required=False,
max_length=1024
)
async def on_submit(self, interaction: discord.Interaction):
cog = interaction.client.get_cog('Suggestions')
if self.reason.value != "":
nmsg = await Suggestions._interaction_finish_suggestion(cog, interaction, self.message, True, self.reason.value)
else:
nmsg = await Suggestions._interaction_finish_suggestion(cog, interaction, self.message, True, None)
msg = await interaction.response.send_message(content=f"Suggestion approved!\nJump Link: {nmsg.jump_url}", ephemeral=True)
await msg.delete(10)
class SuggestionDenyModal(discord.ui.Modal, title="Denying suggestion..."):
def __init__(self, message):
super().__init__()
self.message: discord.Message = message
reason = discord.ui.TextInput(
label="Denial Reason",
placeholder="Why are you denying this suggestion?",
style=discord.TextStyle.paragraph,
required=False,
max_length=1024
)
async def on_submit(self, interaction: discord.Interaction):
cog = interaction.client.get_cog('Suggestions')
if self.reason.value != "":
nmsg = await Suggestions._interaction_finish_suggestion(cog, interaction, self.message, False, self.reason.value)
else:
nmsg = await Suggestions._interaction_finish_suggestion(cog, interaction, self.message, False, None)
msg: discord.Message = await interaction.response.send_message(content=f"Suggestion denied!\nJump Link: {nmsg.jump_url}", ephemeral=True)
await msg.delete(10)
@app_commands.context_menu(name="Approve Suggestion")
async def approve_context(interaction: discord.Interaction, message: discord.Message):
if message.author.id == interaction.client.user.id and len(message.embeds) == 1 and message.embeds[0].title.startswith('Suggestion #'):
await interaction.response.send_modal(SuggestionApproveModal(message))
else:
await interaction.response.send_message(content="This is not a suggestion!", ephemeral=True)
@app_commands.context_menu(name="Deny Suggestion")
async def deny_context(interaction: discord.Interaction, message: discord.Message):
if message.author.id == interaction.client.user.id and len(message.embeds) == 1 and message.embeds[0].title.startswith('Suggestion #'):
await interaction.response.send_modal(SuggestionDenyModal(message))
else:
await interaction.response.send_message(content="This is not a suggestion!", ephemeral=True)
await ctx.tick()

View file

@ -1,11 +1,10 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing SugonCredit!\n**Please load the Economy cog before loading this cog.**\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs.",
"author" : ["SeaswimmerTheFsh"],
"install_msg" : "Thank you for installing SugonCredit!\n**Please load the Bank cog before loading this cog.**\nYou can find the source code of this cog here: https://github.com/SeaswimmerTheFsh/GalaxyCogs.",
"name" : "SugonCredit",
"short" : "Simple points system.",
"description" : "Implements a way for moderators to give out social-credit like points, dubbed 'sugoncredits' by the community.",
"tags" : ["economy"],
"tags" : ["bank"],
"end_user_data_statement": "This cog stores no end user data.",
"hidden": true,
"disabled": false
"requirements": ["inflect", "tabulate"]
}

View file

@ -1,61 +1,140 @@
import sqlite3
from sqlite3 import Error
import discord
from redbot.core import commands, bank, data_manager
from redbot.core import Config, checks, commands, data_manager
from tabulate import tabulate
class SugonCredit(commands.Cog):
"""Implements a way for moderators to give out social-credit like points, dubbed 'sugoncredits' by the community."""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=47252584)
self.config.register_guild(
bank_name = "Social Credit Enforcement Agency",
currency_name = "Social Credit",
max_bal = 1000000000,
min_bal = -1000000000
)
self.data_path = data_manager.cog_data_path(self) / "credit.db"
con = sqlite3.connect(f'{self.data_path}')
con.commit()
con.close()
@commands.hybrid_group(autohelp=True, aliases=["sugoncredit"])
def pluralize(word, count):
if count == 1:
return word
elif word.endswith('s') or word.endswith('x') or word.endswith('z') or word.endswith('ch') or word.endswith('sh'):
return word + 'es'
elif word.endswith('y'):
# Change 'y' to 'ies' for words ending with a consonant + 'y'
return word[:-1] + 'ies'
else:
return word + 's'
def new_guild_generation(self, guild_id):
"""Adds a new table for a guild to the SQLite database."""
con = sqlite3.connect(self.data_path)
cur = con.cursor()
try:
cur.execute(f"SELECT 1 FROM '{guild_id}' LIMIT 1;")
except sqlite3.OperationalError:
cur.execute(f"CREATE TABLE '{guild_id}' (user_id TEXT, balance REAL);")
con.commit()
con.close()
def new_user_generation(self, guild_id, target):
"""Adds a new user to the SQLite database."""
con = sqlite3.connect(f'{self.data_path}')
cur = con.cursor()
cur.execute(f'''INSERT INTO {guild_id}
VALUES ({target.id}, 250);''')
con.commit()
con.close()
@commands.group(autohelp=True, aliases=["sugoncredit"])
@commands.guild_only()
async def credit(self, ctx: commands.Context):
async def credit(self, ctx):
"""Simple points system."""
@credit.command()
async def balance(self, ctx: commands.Context, user: discord.Member = None):
"""Checks an account's balance."""
bank_name = await bank.get_bank_name(ctx.guild)
currency_name = await bank.get_currency_name(ctx.guild)
if user is None:
bal = await bank.get_balance(ctx.author)
target = ctx.author
else:
bal = await bank.get_balance(user)
target = user
output_bal = (f'{bal:,}')
if bal in (1, -1):
embed=discord.Embed(title=f"{bank_name} - Balance", color=await self.bot.get_embed_color(None), description=f"{target.mention} has {output_bal} {currency_name}.")
else:
embed=discord.Embed(title=f"{bank_name} - Balance", color=await self.bot.get_embed_color(None), description=f"{target.mention} has {output_bal} {currency_name}s.")
await ctx.send(embed=embed)
@commands.guild_only()
async def leaderboard(self, ctx, page: int = 1):
"""Shows the individuals with the highest balances."""
await ctx.send(content="This command isn't done yet!")
con = sqlite3.connect(f'{self.data_path}')
cur = con.cursor()
await self.new_guild_generation(self, ctx.guild.id)
bank_name = await self.config.guild(ctx.guild).bank_name()
currency_name = await self.config.guild(ctx.guild).currency_name()
offset = (page - 1) * 10
raw_list = cur.execute(f'''SELECT user_id, balance FROM {ctx.guild.id}
ORDER BY balance DESC
LIMIT 10 OFFSET {offset};''')
await ctx.send(content=f"{raw_list}")
@credit.command()
@commands.guild_only()
async def balance(self, ctx, user: discord.Member = None):
"""Checks an account's balance."""
target = user if user else ctx.author
con = sqlite3.connect(self.data_path)
cur = con.cursor()
await self.new_guild_generation(ctx.guild.id)
bank_name = await self.config.guild(ctx.guild).get_raw('bank_name', default="Bank")
currency_name = await self.config.guild(ctx.guild).get_raw('currency_name', default="Credit")
cur.execute(f"SELECT user_id FROM {ctx.guild.id} WHERE user_id = ?;", (target.id,))
if not cur.fetchone():
await self.new_user_generation(ctx.guild.id, target)
cur.execute(f"SELECT balance FROM {ctx.guild.id} WHERE user_id = ?;", (target.id,))
bal = cur.fetchone()[0]
output_bal = f'{bal:,}'
pluralized_currency_name = await self.pluralize(currency_name, bal)
embed_title = f"{bank_name} - Balance"
embed_color = await self.bot.get_embed_color(None)
embed_description = f"{target.mention} has {output_bal} {pluralized_currency_name}."
embed = discord.Embed(title=embed_title, color=embed_color, description=embed_description)
await ctx.send(embed=embed)
con.close()
@credit.command()
@commands.guild_only()
@commands.mod()
async def add(self, ctx: commands.Context, target: discord.Member, amount: int):
async def add(self, ctx, target: discord.Member, amount: int):
"""Adds credits to an account."""
try:
val = int(amount)
except ValueError:
await ctx.send(content="``amount`` must be a number! Please try again.")
return
con = sqlite3.connect(f'{self.data_path}')
cur = con.cursor()
await self.new_guild_generation({ctx.guild.id})
image = discord.File(fp=data_manager.bundled_data_path(self) / "add.png", filename="Add.png")
bank_name = await bank.get_bank_name(ctx.guild)
currency_name = await bank.get_currency_name(ctx.guild)
current_bal = await bank.get_balance(target)
max_bal = await bank.get_max_balance(ctx.guild)
bank_name = await self.config.bank_name()
currency_name = await self.config.currency_name()
max_bal = await self.config.max_bal()
min_bal = await self.config_min_bal()
current_bal = cur.execute(f'''SELECT balance FROM {ctx.guild.id}
WHERE user_id = {target.id};''')
new_bal = current_bal + amount
output_amount = (f'{val:,}')
output_new_bal = (f'{new_bal:,}')
output_max_bal = (f'{max_bal:,}')
output_min_bal = (f'{min_bal:,}')
if new_bal > max_bal:
await ctx.send(content=f"You are attempting to set {target.mention}'s balance to above {output_max_bal}. Please try again!")
elif new_bal < 0:
await ctx.send(content=f"You are attempting to set {target.mention}'s balance to below 0. Please try again!")
return
elif new_bal < min_bal:
await ctx.send(content=f"You are attempting to set {target.mention}'s balance to below {output_min_bal}. Please try again!")
elif ctx.guild.id == 204965774618656769:
logging_channel: discord.TextChannel = self.bot.get_channel(1082495815878189076)
await bank.deposit_credits(target, amount=amount)
logging_channel = self.bot.get_channel(1082495815878189076)
cur.execute(f'''UPDATE {ctx.guild.id}
SET balance = {new_bal}
WHERE user_id = {target.id};''')
await ctx.send(content=f"{target.mention} now has {output_amount} more SugonCredit, with a total of {output_new_bal}!")
if amount in (1, -1):
if amount == 1 or amount == -1:
await target.send(content=f"You gained {output_amount} SugonCredit! Good work community member! You now have {output_new_bal} SugonCredits.", file=image)
else:
await target.send(content=f"You gained {output_amount} SugonCredits! Good work community member! You now have {output_new_bal} SugonCredits.", file=image)
@ -63,12 +142,17 @@ class SugonCredit(commands.Cog):
await logging_channel.send(embed=logging_embed)
elif ctx.guild.id != 204965774618656769:
embed=discord.Embed(title=f"{bank_name} - Add", color=await self.bot.get_embed_color(None), description=f"{target.mention}'s {currency_name} balance has been increased by {output_amount}.\nCurrent balance is {output_new_bal}.")
await bank.deposit_credits(target, amount=amount)
cur.execute(f'''UPDATE {ctx.guild.id}
SET balance = {new_bal}
WHERE user_id = {target.id};''')
await ctx.send(embed=embed)
con.commit()
con.close()
@credit.command()
@commands.guild_only()
@commands.mod()
async def remove(self, ctx: commands.Context, target: discord.Member, amount: int):
async def remove(self, ctx, target: discord.Member, amount: int):
"""Removes credits from an account."""
try:
val = int(amount)
@ -76,19 +160,32 @@ class SugonCredit(commands.Cog):
await ctx.send(content="``amount`` must be a number. Please try again!")
return
image = discord.File(fp=data_manager.bundled_data_path(self) / "remove.mp4", filename="MEGA_BASE.mp4")
bank_name = await bank.get_bank_name(ctx.guild)
currency_name = await bank.get_currency_name(ctx.guild)
current_bal = await bank.get_balance(target)
data_path = data_manager.cog_data_path(self) / "credit.db"
con = sqlite3.connect(f'{data_path}')
cur = con.cursor()
await self.new_guild_generation({ctx.guild.id})
bank_name = await self.config.bank_name()
currency_name = await self.config.currency_name()
max_bal = await self.config.max_bal()
min_bal = await self.config_min_bal()
current_bal = cur.execute(f'''SELECT balance FROM {ctx.guild.id}
WHERE user_id = {target.id};''')
new_bal = current_bal - amount
output_amount = (f'{val:,}')
output_new_bal = (f'{new_bal:,}')
if new_bal < 0:
await ctx.send(content=f"You are attempting to set {target.mention}'s balance to below 0. Please try again!")
output_max_bal = (f'{max_bal:,}')
output_min_bal = (f'{min_bal:,}')
if new_bal > max_bal:
await ctx.send(content=f"You are attempting to set {target.mention}'s balance to above {output_max_bal}. Please try again!")
elif new_bal < min_bal:
await ctx.send(content=f"You are attempting to set {target.mention}'s balance to below {output_min_bal}. Please try again!")
elif ctx.guild.id == 204965774618656769:
await bank.withdraw_credits(target, amount=amount)
logging_channel: discord.TextChannel = self.bot.get_channel(1082495815878189076)
cur.execute(f'''UPDATE {ctx.guild.id}
SET balance = {new_bal}
WHERE user_id = {target.id};''')
logging_channel = self.bot.get_channel(1082495815878189076)
await ctx.send(content=f"{target.mention} now has {output_amount} less SugonCredit, with a total of {output_new_bal}!\nIf this is a punishment, do better Galaxy Player! Re-education mods will be sent to your DM's if your SugonCredit drops to a substantially low amount!")
if amount in (1, -1):
if amount == 1 or amount == -1:
await target.send(content=f"__MESSAGE FROM THE MINISTRY OF THE MEGA BASE__\n\n(我们的) {output_amount} SugonCredit has been taken from your account. Citizen, do not continue to preform bad actions! Glory to the Galaxy Communist Party!", file=image)
else:
await target.send(content=f"__MESSAGE FROM THE MINISTRY OF THE MEGA BASE__\n\n(我们的) {output_amount} SugonCredits have been taken from your account. Citizen, do not continue to preform bad actions! Glory to the Galaxy Communist Party!", file=image)
@ -97,4 +194,8 @@ class SugonCredit(commands.Cog):
elif ctx.guild.id != 204965774618656769:
embed=discord.Embed(title=f"{bank_name} - Remove", color=await self.bot.get_embed_color(None), description=f"{target.mention}'s {currency_name} balance has been decreased by {output_amount}.\nCurrent balance is {output_new_bal}.")
await ctx.send(embed=embed)
await bank.withdraw_credits(target, amount=val)
cur.execute(f'''UPDATE {ctx.guild.id}
SET balance = {new_bal}
WHERE user_id = {target.id};''')
con.commit()
con.close()

View file

@ -1,5 +0,0 @@
from .worldzero import WorldZero
async def setup(bot):
await bot.add_cog(WorldZero(bot))

View file

@ -1,10 +0,0 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing World Zero!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"name" : "World Zero",
"short" : "This cog is meant to provide random functions for my crippling World Zero addiction!",
"description" : "This cog is meant to provide random functions for my crippling World Zero addiction!",
"end_user_data_statement" : "This cog does not store any End User Data.",
"hidden": true,
"disabled": false
}

View file

@ -1,37 +0,0 @@
import discord
from redbot.core import commands
class WorldZero(commands.Cog):
"""This cog is meant to provide random functions for my crippling World Zero addiction!
Developed by cswimr."""
def __init__(self, bot):
self.bot = bot
@commands.group(name="worldzero", invoke_without_command=True, aliases=['wz'])
async def worldzero(self, ctx: commands.Context):
"""Tells the user that this command doesn't do anything currently."""
await ctx.send("This command doesn't do anything currently, have you tried a subcommand?\nCurrent subcommands:\n- `-worldzero upgrade` - Checks what the Attack Power/Health of an item will be after upgrading it.\n - See `-help worldzero upgrade` for more information.")
@worldzero.command(name="upgrade")
async def worldzero_upgrade(self, ctx: commands.Context, power_amount: str, upgrade_amount: str):
"""Checks what the Attack Power/Health of an item will be after upgrading it.
**Arguments**
- The `power_amount` argument is the Attack Power/Health of the item you're looking to upgrade.
- The `upgrade_amount` argument is the number of times your item can be upgraded."""
try:
stat_int = int(f"{power_amount}".replace(",", ""))
upgrade_int = int(f"{upgrade_amount}".replace(",", ""))
except ValueError:
await ctx.send(content="Please input a number!")
return
math = round(stat_int + ((stat_int/15)*upgrade_int))
output_from = f'{stat_int:,}'
output_to = f'{math:,}'
embed = discord.Embed(color=await self.bot.get_embed_color(None))
embed.add_field(name="Default Power", value=f"{output_from}", inline=False)
embed.add_field(name="Upgraded Power", value=f"{output_to}", inline=False)
await ctx.send(embed=embed)

View file

@ -1,5 +0,0 @@
from .youtubedownloader import YouTubeDownloader
async def setup(bot):
await bot.add_cog(YouTubeDownloader(bot))

View file

@ -1,11 +0,0 @@
{
"author" : ["cswimr"],
"install_msg" : "Thank you for installing YouTubeDownloader!\nYou can find the source code of this cog here: https://coastalcommits.com/cswimr/GalaxyCogs",
"name" : "YouTubeDownloader",
"short" : "Custom cog intended for use on the Galaxy discord server.",
"description" : "Custom cog intended for use on the Galaxy discord server.",
"end_user_data_statement" : "This cog does not store any End User Data.",
"requirements": ["pytube"],
"hidden": false,
"disabled": false
}

View file

@ -1,160 +0,0 @@
import asyncio
import os
import re
import discord
from redbot.core import Config, checks, commands, data_manager
from pytube import YouTube, exceptions
class YouTubeDownloader(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=475728338)
self.config.register_global(
save_directory = str(data_manager.cog_data_path()) + f"{os.sep}YouTubeDownloader",
blacklisted_users = []
)
class UserBlacklisted(Exception):
def __init__(self, message="The user is blacklisted from using this command."):
super().__init__(message)
async def blacklist_checker(self, user_id):
blacklisted_users = await self.config.blacklisted_users()
for blacklisted_user_id in blacklisted_users:
if blacklisted_user_id == user_id:
raise self.UserBlacklisted
@commands.command()
@checks.is_owner()
async def change_data_path(self, ctx: commands.Context, *, data_path: str = None):
"""This command changes the data path the `[p]download` command outputs to."""
old_path = await self.config.save_directory()
if not data_path:
await ctx.send(f"The current data path is `{old_path}`.")
return
if os.path.isdir(data_path):
await self.config.save_directory.set(data_path)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"The save directory has been set to `{data_path}`.\n It was previously set to `{old_path}`.")
await ctx.send(embed=embed)
elif os.path.isfile(data_path):
await ctx.send("The path you've provided leads to a file, not a directory!")
elif os.path.exists(data_path) is False:
await ctx.send("The path you've provided doesn't exist!")
@commands.command(aliases=["dl"])
async def download(self, ctx: commands.Context, url: str, audio_only: bool = True, delete: bool = True, *, subfolder: str = None):
"""This command downloads a YouTube Video as an `m4a` (or `mp4`) and uploads the file to discord.
If you're considered a bot owner, you will be able to save downloaded files to the data path set in the `[p]change_data_path` command.
**Arguments**
- The `url` argument is just the url of the YouTube Video you're downloading.
- The `audio_only` argument determines if the video will be an `m4a` file or an `mp4` file.
- The `delete` argument will automatically delete the file after uploading it to Discord. If set to False, it will only save the file if you are a bot owner.
- The `subfolder` argument only does anything if `delete` is set to False, but it allows you to save to a subfolder in the data path you've set previously without having to change said data path manually."""
try:
await self.blacklist_checker(ctx.author.id)
except self.UserBlacklisted:
await ctx.send("You are blacklisted from running this command!")
return
def youtube_download(url: str, path: str):
"""This function does the actual downloading of the YouTube Video."""
yt = YouTube(url=url)
translation_table = dict.fromkeys(map(ord, r'<>:"/\|?*'), None)
filename = f"{yt.title.translate(translation_table)} ({yt.video_id})"
if audio_only:
stream = yt.streams.filter(only_audio=True, mime_type='audio/mp4')
stream = stream.order_by('abr')
filename_format = filename + ".m4a"
else:
stream = yt.streams.filter(progressive=True, mime_type='video/mp4')
stream = stream.order_by('resolution')
filename_format = filename + ".mp4"
previously_existed = bool(os.path.isfile(path + f"{os.sep}{filename_format}"))
return stream.desc().first().download(filename=filename, output_path=path), previously_existed, filename_format
data_path = await self.config.save_directory()
if subfolder and await self.bot.is_owner(ctx.author):
data_path = os.path.join(data_path, subfolder)
illegal_chars = r'<>:"/\|?*'
if any(char in illegal_chars for char in subfolder):
pattern = "[" + re.escape(illegal_chars) + "]"
modified_subfolder = re.sub(pattern, r'__**\g<0>**__', subfolder)
await ctx.send(f"Your subfolder contains illegal characters: `{modified_subfolder}`")
elif os.path.isfile(data_path):
await ctx.send("Your 'subfolder' is a file, not a directory!")
elif os.path.exists(data_path) is False:
message = await ctx.send("Your subfolder does not exist yet, would you like to continue? It will be automatically created.")
def check(message):
return message.author == ctx.author and message.content.lower() in ['yes', 'ye', 'y', '1']
try:
await self.bot.wait_for('message', check=check, timeout=60)
except asyncio.TimeoutError:
await message.edit("You took too long to respond.")
else:
await message.edit("Confirmed!")
try:
os.makedirs(data_path)
except OSError as e:
await message.edit(f"Encountered an error attempting to create the subfolder!\n`{e}`")
msg = message.edit
else:
msg = ctx.send
message = await msg("YouTube Downloader started!")
try:
output = youtube_download(url, data_path)
except exceptions.RegexMatchError:
await message.edit(content="Please provide a link to YouTube and not another site.")
return
while not os.path.isfile(output[0]):
await asyncio.sleep(0.2)
if os.path.isfile(output[0]):
with open(output[0], 'rb') as file:
try:
complete_message = await ctx.send(content="YouTube Downloader completed!\nDownloaded file:", file=discord.File(file, output[2]))
except ValueError:
complete_message = await ctx.send(content="YouTube Downloader completed, but the file was too large to upload.")
file.close()
if delete is True or await self.bot.is_owner(ctx.author) is False:
if output[1] is False:
os.remove(output[0])
await complete_message.edit(content="YouTube Downloader completed!\nFile has been deleted.\nDownloaded file:")
if output[1] is True:
await complete_message.edit(content="YouTube Downloader completed!\nFile has not been deleted, as it was previously downloaded and saved.\nDownloaded file:")
@commands.group(name="dl-blacklist", invoke_without_command=True)
async def blacklist(self, ctx: commands.Context, user: discord.User):
"""Group command for managing the blacklist."""
for user_id in await self.config.blacklisted_users():
if user_id == user.id:
await ctx.send(f"{user.mention} is in the blacklist.", allowed_mentions = discord.AllowedMentions(users=False))
return
await ctx.send(f"{user.mention} is not in the blacklist.", allowed_mentions = discord.AllowedMentions(users=False))
@blacklist.command(name='add')
@checks.is_owner()
async def blacklist_add(self, ctx: commands.Context, user: discord.User):
blacklisted_users: list = await self.config.blacklisted_users()
for user_id in blacklisted_users:
if user_id == user.id:
await ctx.send(f"{user.mention} is already in the blacklist.")
return
blacklisted_users.append(user.id)
await self.config.blacklisted_users.set(blacklisted_users)
await ctx.send(f"{user.mention} has been added to the blacklist.")
@blacklist.command(name='remove')
@checks.is_owner()
async def blacklist_remove(self, ctx: commands.Context, user: discord.User):
blacklisted_users: list = await self.config.blacklisted_users()
for user_id in blacklisted_users:
if user_id == user.id:
blacklisted_users.remove(user_id)
await self.config.blacklisted_users.set(blacklisted_users)
await ctx.send(f"{user.mention} has been removed from the blacklist.")
return
await ctx.send(f"{user.mention} is not in the blacklist.")