Skip to content

Commit

Permalink
Merge pull request #31 from Soapy7261/main
Browse files Browse the repository at this point in the history
Python rewrite
  • Loading branch information
JoshuaSlui authored Jan 31, 2023
2 parents dd11d83 + e6a2efa commit b8298d7
Show file tree
Hide file tree
Showing 21 changed files with 456 additions and 47 deletions.
3 changes: 0 additions & 3 deletions .github/CODEOWNERS

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ name: "CodeQL"

on:
push:
branches: [ main ]
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
branches: [ "main" ]
schedule:
- cron: '24 2 * * 1'
- cron: '34 0 * * 2'

jobs:
analyze:
Expand All @@ -32,39 +32,45 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main

# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality


# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

#- run: |
# make bootstrap
# make release
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
26 changes: 26 additions & 0 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Pylint

on: [push]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10.9", "3.11.1"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install pylint
run: |
python -m pip install --upgrade pip
pip install pylint
- name: Install dependencies
run: |
pip install -r requirements.txt
- name: Analysing the code with pylint
run: |
pylint $(git ls-files '*.py')
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
config.json
node_modules
.env
.env.local
.env.development
local.gitignore
.idea
.vscode
cogs/__pycache__
__pycache__
2 changes: 2 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[MESSAGES CONTROL]
disable=line-too-long,missing-function-docstring,missing-class-docstring,missing-module-docstring,too-few-public-methods,no-name-in-module,global-statement
66 changes: 66 additions & 0 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Configuration
Pingernos py offers three different ways to configure it, a config file, environment variables and a .env
If you wish to use the config file, you must set the `use_json` variable in [getdata](./utils.py) to `True` and copy the [example.config.json](./example.config.json) to a new file called config.json in the root folder and modify the options in it.
If you wish to use a .env file, just copy the [example.env](./example.env) to a new file called .env in the root folder and modify the options in it, you can use environment variables and a .env file at the same time if you so desire.
Environment variables use `SCREAMING_SNAKE_CASE`, the configuration file uses `PascalCase`.

If a config file is missing, pingernos will try to load the environment variables. If both are missing, pingernos will exit.

## Auth Token (required)
Discord bot authentication token, can be generated in the [Developer Portal](https://discord.com/developers/applications/)

| type | config file | environment |
|--------|-------------|---------------------|
| string | `Token` | `TOKEN` |

## Prefix (required)
Prefix to use for commands, can be a mention or a string

| type | config file | environment |
|--------|-------------|---------------------|
| string | `Prefix` | `PREFIX` |

## Owners (required)
Array of user ids that are allowed to use owner only features

| type | config file | environment |
|----------|--------------------|----------------------------|
| string[] | `Owners` | `OWNERS` |

## Database (required)
MySQL/MariaDB access credentials. Other SQL dialects or Databases are not supported.

### Host
Database hostname or IP

| type | config file | environment |
|--------|-----------------|------------------------|
| string | `Database.Host` | `DB_HOST` |

### User
Database username

| type | config file | environment |
|--------|-----------------|------------------------|
| string | `Database.User` | `DB_USER` |

### Password
Database password

| type | config file | environment |
|--------|---------------------|----------------------------|
| string | `Database.Password` | `DB_PASSWORD` |

### Database
Database name

| type | config file | environment |
|--------|---------------------|----------------------------|
| string | `Database.Database` | `DB_DATABASE` |

### Port
Database port

| type | config file | environment |
|--------|-----------------|------------------------|
| int | `Database.Port` | `DB_PORT` |
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Pingernos
# About
This is a fork of pingernos written in py-cord, this is not affiliated with the original pingernos bot or Aternos

# Original README.md

## Pingernos
Pingernos is a Discord bot that lets you grab the status of any Aternos server.

This bot takes **mentions** as prefix. You can use **<@889197952994791434> help** to view a list of the commands.
Expand All @@ -14,5 +19,5 @@ The API we use is not affiliated with Aternos, Minecraft or any server host. Thi

You can invite the bot here: https://discord.com/api/oauth2/authorize?client_id=889197952994791434&permissions=274878286848&scope=bot

## NOTE
Pingernos has been transferred to BlackFur Studios ORG. and will from now on fall under authority and legal notice/compliance of BlackFur Studios ORG. The privacy policy and legal terms of former PsychOps Studios are no longer present and will be rewritten in name of BlackFur Studios. Please bear with us as we attempt to do this as fast as we can. BlackFur Studios ORG. does not have any affiliations with the now-inactive PsychOps Studios and only takes authority over Pingernos and any entities that are directly related to Pingernos.
### NOTE
Pingernos has been transferred to BlackFur Studios ORG. and will from now on fall under authority and legal notice/compliance of BlackFur Studios ORG. The privacy policy and legal terms of former PsychOps Studios are no longer present and will be rewritten in name of BlackFur Studios. Please bear with us as we attempt to do this as fast as we can. BlackFur Studios ORG. does not have any affiliations with the now-inactive PsychOps Studios and only takes authority over Pingernos and any entities that are directly related to Pingernos.
40 changes: 40 additions & 0 deletions cogs/checkip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#from re import match
from discord.ext import commands, bridge
from discord import Embed
from mcstatus import JavaServer
from utils import Utils
class CheckIP(commands.Cog):
def __init__(self, bot):
self.bot = bot

@bridge.bridge_command(aliases=["checkserverip", "check"], description="Checks if an Aternos-IP is free to use.")
async def checkip(self, ctx, address = None):
if address is None:
return await ctx.respond("Please provide a Aternos server ip!\nExample: example.aternos.me")
#if not match(r"^(\w+)(?:\.aternos\.me)?$", address):
# return await ctx.respond(f"`{address}`is not a valid Aternos server IP or name.")
if not address.endswith(".aternos.me"):
address += ".aternos.me"
if address.count(".") > 2:
return await ctx.respond("Please provide a valid Aternos server ip!\nExample: example.aternos.me")
nip = address.split(".")[0]
if len(nip) > 20:
return await ctx.respond("Aternos IPs can only be 20 characters long, please try a shorter one. Yours is " + str(len(nip)) + " characters long.")
if len(nip) < 4:
return await ctx.respond("Aternos IPs must be at least 4 characters long, please try a longer one. Yours is " + str(len(nip)) + " characters long.")
#async with ctx.typing():
await ctx.defer()
embed = Embed()
server = await JavaServer.async_lookup(address)
stat = await server.async_status()
if stat.version.name == "⚠ Error":
embed.description=f"**{address}** is free to use!\nTo use it as your server address, head to **[the options of your server](https://aternos.org/options)**"
embed.colour = Utils.Colors.green
else:
embed.description=f"**{address}** is already taken!"
embed.colour = Utils.Colors.red
await ctx.respond(embed=embed)


def setup(bot):
bot.add_cog(CheckIP(bot))
50 changes: 50 additions & 0 deletions cogs/cogs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from os import listdir
from discord.ext.commands import slash_command
from discord.ext import commands
from discord import Option
#from discord.errors import ExtensionAlreadyLoaded
from utils import Utils
class Cogs(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.info = Utils.get_data()

def getcogs(self, ctx):
if ctx.interaction.user.id not in self.info['Owners']:
return ["You are not an owner of the bot!"]
cogs = []
for file in listdir("./cogs"):
if file.endswith(".py"):
cogs.append(file[:-3])
return cogs

@slash_command(description='Only the owners of the bot can run this command', guild_ids=[1041398130677141564])
async def cogs(self, ctx, action: Option(choices=["Load", "Unload", "Reload"]), cog: Option(autocomplete=getcogs)):
if ctx.author.id not in self.info['Owners']:
return
if cog.lower() not in [f"{fn[:-3]}" for fn in listdir("./cogs")]:
await ctx.respond("That cog doesn't exist!", ephemeral=True)
return
if action.lower() not in ["load", "unload", "reload"]:
await ctx.respond("That action doesn't exist!", ephemeral=True)
return
await ctx.defer()
try:
if action == "Load":
self.bot.load_extension(f"cogs.{cog}")
elif action == "Unload":
self.bot.unload_extension(f"cogs.{cog}")
elif action == "Reload":
self.bot.reload_extension(f"cogs.{cog}")
except Exception as error:
await ctx.respond(f"An error has occured!\n{error}")
raise error
try:
await self.bot.sync_commands()
except Exception as error:
await ctx.respond(f"An error has occured!\n{error}")
raise error
await ctx.respond(f"{action}ed {cog} and reloaded all commands!")

def setup(bot):
bot.add_cog(Cogs(bot))
19 changes: 19 additions & 0 deletions cogs/error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from discord.ext import commands
class Error(commands.Cog):
def __init__(self, bot):
self.bot = bot

@commands.Cog.listener()
async def on_command_error(self, ctx, error):
if isinstance(error, commands.CommandNotFound):
return await ctx.respond("That command doesn't exist!")
await ctx.respond ("An unknown error has occured!\nThis has been logged")
raise error

@commands.Cog.listener()
async def on_application_command_error(self, ctx, error):
await ctx.respond ("An unknown error has occured!\nThis has been logged")
raise error

def setup(bot):
bot.add_cog(Error(bot))
16 changes: 16 additions & 0 deletions cogs/guilds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from discord.ext import commands, bridge
from discord import Embed
from utils import Utils
class Guilds(commands.Cog):
def __init__(self, bot):
self.bot = bot

@bridge.bridge_command(aliases=["servers"], description = "Shows how many guilds the bot is in.")
async def guilds(self, ctx):
embed = Embed()
embed.description = f"{self.bot.user.name} is currently in {len(self.bot.guilds)} servers with a total of {sum(x.member_count for x in self.bot.guilds)} users."
embed.color = Utils.Colors.blue
await ctx.respond(embed=embed)

def setup(bot):
bot.add_cog(Guilds(bot))
18 changes: 18 additions & 0 deletions cogs/ping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from asyncio import wait_for
from discord.ext import commands, bridge
from utils import Utils
class Ping(commands.Cog):
def __init__(self, bot):
self.bot = bot

@bridge.bridge_command(aliases=["latency", "pong"], description="Get the bot and websocket latency")
async def ping(self, ctx):
#await ctx.defer()
try:
stat = await wait_for(Utils.get_server_status("example.aternos.me"), timeout=2)
except TimeoutError:
return await ctx.respond(f"Uh oh! The protocol took too long to respond! This will likely fix itself.\nAPI Latency is {round(self.bot.latency*1000, 2)}ms")
await ctx.respond(content=f"API Latency is {round(self.bot.latency*1000, 2)}ms\nProtocol: {round(stat.latency)}ms")

def setup(bot):
bot.add_cog(Ping(bot))
16 changes: 16 additions & 0 deletions cogs/privacy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from discord.ext import commands, bridge
from discord import Embed
from utils import Utils
class Privacy(commands.Cog):
def __init__(self, bot):
self.bot = bot

@bridge.bridge_command(description = "Shows the privacy policy of the bot.")
async def privacy(self, ctx):
embed = Embed()
embed.description = f"{self.bot.user.name} saves a minimal amount of data to allow for its functionality. As we work on regaining full functionality, we do not currently collect anything On our database storage, we currently only have server IPs and guild IDs stored. For any concerns, Mail to miataboymx@gmail.com"
embed.colour = Utils.Colors.blue
await ctx.respond(embed=embed)

def setup(bot):
bot.add_cog(Privacy(bot))
14 changes: 14 additions & 0 deletions cogs/setserver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from discord.ext import commands#, bridge
class SetServer(commands.Cog):
def __init__(self, bot):
self.bot = bot

#@bridge.bridge_command(aliases=["set"], description="Set the default server to use if no argument is provided in the status command.")
#async def setserver(self, ctx, server = None):
# if server is None:
# return await ctx.respond("Please provide a server IP.")
# await ctx.defer()
#This is up to Miataboy to implement

def setup(bot):
bot.add_cog(SetServer(bot))
Loading

0 comments on commit b8298d7

Please sign in to comment.