Skip to content

Commit

Permalink
Merge pull request #21 from ufosc/develop
Browse files Browse the repository at this point in the history
Merge develop into master

Changes:
- Added a database backend
- Added error message handling
- Added a welcome message for new members
- Add a lot of helloworld texts
  • Loading branch information
hjarrell authored Oct 4, 2018
2 parents 4d6390c + da65a41 commit 06ecf1c
Show file tree
Hide file tree
Showing 41 changed files with 663 additions and 24 deletions.
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true

[*.py]
indent_style = space
indent_size = 4

[*.md]
trim_trailing_whitespace = false
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
__pycache__/
*.jpg
config.py
database/data/sqlite3.db
17 changes: 12 additions & 5 deletions ALBot.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
import discord
from discord.utils import get
from discord.ext import commands

import cogs.CONSTANTS as CONSTANTS
import config

'''Cogs to load when the bot first starts'''
startup_cogs = [
"cogs.messages",
"cogs.errors",
"cogs.helloworld",
"cogs.memes",
"cogs.projects",
"cogs.admin",
"cogs.music",
"cogs.compile"
"cogs.compile",
"cogs.welcome"
]

bot_url = 'https://discordapp.com/api/oauth2/authorize?client_id={0}&scope=bot&permissions=0'

bot = commands.Bot(command_prefix="!", description="ALBot (A Lame Bot)", case_insensitive=True, command_not_found="Invalid command: {}")

@bot.event
async def on_ready():
"""Print the bots information on connect"""
print('Logged in as')
print(bot.user.name)
print(bot.user.id)
global bot_url
print('Logged in as "{name}" with id {id}'.format(name=bot.user.name,id=bot.user.id))
print('Invite URL: {iurl}'.format(iurl=bot_url.format(bot.user.id)))
print('-----')
await bot.change_presence(activity=discord.Game(name="Destroying propritary software"))

if __name__ == "__main__":
for extension in startup_cogs:
try:
Expand Down
20 changes: 20 additions & 0 deletions cogs/CONSTANTS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

# Misc
ERROR_REPORT_URL = 'https://github.com/ufosc/albot-and-albot'
BOT_NAME = 'ALBot'

# Embed colors
EMBED_COLOR_STANDARD = 0x00529b
EMBED_COLOR_ERROR = 0x913232

# Message reaction types
# 'CONFLICT' means that this reaction type MUST be unique, or at least
# not be the same as another CONFLICT-type reaction, as the program
# could potentially use this reaction as a user-input button.
REACTION_DELETE = '\U0001f6ae' # CONFLICT
REACTION_NEW = '\u2733' # CONFLICT
REACTION_EXPAND = '\U0001f521' # CONFLICT
REACTION_DENY = '\u26d4' #
REACTION_ERROR = '\u26a0' #
REACTION_NOT_FOUND = '\u2139' # Same as REACTION_INFO
REACTION_INFO = '\u2139' # Same as REACTION_NOT_FOUND
4 changes: 2 additions & 2 deletions cogs/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async def reload(self, ctx, extension_name : str):
@commands.check(cogs.util.is_officer_check)
async def whereami(self, ctx):
await ctx.send("You are in {} with id {}".format(ctx.channel.name, ctx.channel.id))

@commands.command(hidden=True, name="eval")
@commands.check(cogs.util.is_owner)
async def admin_eval(self, ctx, *, cmd : str):
Expand All @@ -77,7 +77,7 @@ async def admin_eval(self, ctx, *, cmd : str):
exec(cmd_body, env)
except Exception as e:
return await ctx.send("```py\n{0.__class__.__name__}: {0}\n```", e)

try:
with redirect_stdout(stdout):
ret = await eval("__admin_eval()", env)
Expand Down
4 changes: 2 additions & 2 deletions cogs/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ async def compile_langs(self, ctx):

for lang in langs.json():
self.complangs.append("{} | {}\n".format(lang['id'], lang['name']))

response_text = "ID | Name\n"
for lang in self.complangs:
response_text += lang
await ctx.send(response_text)

@commands.command(name="compile")
async def _compile(self, ctx, lang_id : int, *, program : str):
'''Compiles and runs code using the judge0 api'''
Expand Down
106 changes: 106 additions & 0 deletions cogs/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import sys
import traceback
import math

import discord
from discord.ext import commands

import cogs.CONSTANTS as CONSTANTS
from database.database import SQLCursor, SQLConnection
from cogs.messages import track

class ALBotErrorHandlers:
""" Handles errors """

def __init__(self, bot, db):
self.bot = bot
self.db = db

def _construct_error_embed(self, command_name, error_name, error_text, full_command_string, full_backtrace=None):
title = "{err} An error was encountered while processing the {0} command".format(command_name, err=CONSTANTS.REACTION_ERROR)
embed = discord.Embed(title=title, colour=discord.Colour(CONSTANTS.EMBED_COLOR_ERROR), description="**{0}**: ```{1}```".format(error_name, str(error_text)))
embed.set_footer(text="Report bugs at {url}".format(url=CONSTANTS.ERROR_REPORT_URL))
embed.add_field(name="While processing the command:", value="``{0}``".format(full_command_string), inline=False)
if full_backtrace:
itr = 1
total_itrs = math.ceil(len(full_backtrace)/512)
while len(full_backtrace) > 0:
if len(full_backtrace) > 512:
embed.add_field(name="Backtrace ({0} of {1}):".format(itr, total_itrs), value="```{0}```".format(full_backtrace[:512]), inline=False)
full_backtrace = full_backtrace[512:]
itr = itr + 1
else:
embed.add_field(name="Backtrace ({0} of {1}):".format(itr, total_itrs), value="```{0}```".format(full_backtrace), inline=False)
break
else:
embed.add_field(name='Press {expand}'.format(expand=CONSTANTS.REACTION_EXPAND), value='for full error backtrace', inline=False)

return embed

def _construct_unknown_command_embed(self, error_text, full_text):
title = "{notfound} Invalid command.".format(notfound=CONSTANTS.REACTION_NOT_FOUND)
embed = discord.Embed(title=title, colour=discord.Colour(CONSTANTS.EMBED_COLOR_ERROR), description='```{0}```'.format(error_text))
embed.set_footer(text="Use {0}help for a list of commands.".format(self.bot.command_prefix))
embed.add_field(name="While processing the command:", value="``{0}``".format(full_text), inline=False)

return embed

async def on_command_error(self, ctx, error):
if type(error) == discord.ext.commands.MissingPermissions:
await ctx.message.add_reaction(CONSTANTS.REACTION_DENY)
embed = discord.Embed(title='{deny} Insufficient Permissions'.format(deny=CONSTANTS.REACTION_DENY), colour=discord.Colour(CONSTANTS.EMBED_COLOR_ERROR), description="You are not permitted to run the command ``{0}``".format(ctx.message.content))
embed.add_field(name="Reason:", value=str(error))
msg = await ctx.send(content='', embed=embed)
await track(msg, ctx.author)
else:
embed = None
if not ctx.command:
embed = self._construct_unknown_command_embed(str(error), ctx.message.content)
else:
embed = self._construct_error_embed(ctx.command.name, str(type(error)), str(error), ctx.message.content)

await ctx.message.add_reaction(CONSTANTS.REACTION_ERROR)
msg = await ctx.send(content='', embed=embed)
await track(msg, ctx.author)
if not ctx.command:
return
await msg.add_reaction(CONSTANTS.REACTION_EXPAND)
with SQLCursor(self.db) as cur:
bt_string = ''.join(traceback.format_exception(type(error), error, error.__traceback__))
print('{bname} encountered an error:\n{0}'.format(bt_string, bname=CONSTANTS.BOT_NAME))
cur.execute('INSERT INTO error_messages (message_id, channel_id, command_name, error_name, error_text, full_backtrace, full_command_string) VALUES (?,?,?,?,?,?,?);',(msg.id, msg.channel.id, ctx.command.name, str(type(error)), str(error), bt_string, ctx.message.content))

async def on_raw_reaction_add(self, payload):
if payload.user_id == self.bot.user.id:
return
elif payload.emoji.name == CONSTANTS.REACTION_EXPAND:
row = None
with SQLCursor(self.db) as cur:
cur.execute('SELECT command_name, error_name, error_text, full_command_string, full_backtrace FROM error_messages WHERE message_id=? AND channel_id=?;',(payload.message_id, payload.channel_id))
row = cur.fetchone()
if not row:
return

to_edit = await self.bot.get_channel(payload.channel_id).get_message(payload.message_id)
new_embed = self._construct_error_embed(row[0],row[1],row[2],row[3],row[4])
await to_edit.edit(content='{err} Command error {err}'.format(err=CONSTANTS.REACTION_ERROR),embed=new_embed)

async def on_raw_reaction_remove(self, payload):
if payload.user_id == self.bot.user.id:
return
if payload.emoji.name == CONSTANTS.REACTION_EXPAND:
row = None
with SQLCursor(self.db) as cur:
cur.execute('SELECT command_name, error_name, error_text, full_command_string, full_backtrace FROM error_messages WHERE message_id=? AND channel_id=?;',(payload.message_id, payload.channel_id))
row = cur.fetchone()
if not row:
return

to_edit = await self.bot.get_channel(payload.channel_id).get_message(payload.message_id)
new_embed = self._construct_error_embed(row[0],row[1],row[2],row[3])
await to_edit.edit(content='{err} Command error {err}'.format(err=CONSTANTS.REACTION_ERROR),embed=new_embed)



def setup(bot):
bot.add_cog(ALBotErrorHandlers(bot, SQLConnection()))
10 changes: 9 additions & 1 deletion cogs/helloworld.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ def __init__(self, bot):
async def hello(self, ctx, lang : str):
'''Prints the hello world source for any language defined in cogs/helloworld'''
for fName in os.listdir("cogs/helloworld"):
if fName.startswith(lang.lower()):
if fName == (lang.lower() + ".txt"):
with open("cogs/helloworld/{}".format(fName), 'r') as f:
await ctx.send(f.read())

@commands.command()
async def hellolangs(self, ctx):
'''Prints all the languages that there are helloworld's for'''
langs = ''
for fName in os.listdir("cogs/helloworld"):
langs += fName.replace('.txt','') + '\n'
await ctx.send(langs)

def setup(bot):
bot.add_cog(HelloWorld(bot))
3 changes: 3 additions & 0 deletions cogs/helloworld/bash.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```bash
echo 'Hello, World!'
```
7 changes: 7 additions & 0 deletions cogs/helloworld/c.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```c
#include <stdio.h>
int main(void) {
puts("Hello, World!");
return 0;
}
```
8 changes: 8 additions & 0 deletions cogs/helloworld/cobol.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
```cobol
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
* simple hello world program
PROCEDURE DIVISION.
DISPLAY 'Hello world!'.
STOP RUN.
```
6 changes: 6 additions & 0 deletions cogs/helloworld/cpp.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```cpp
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
}
```
7 changes: 7 additions & 0 deletions cogs/helloworld/csharp.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```csharp
using System;
public class Program {
public static void Main(string[] args) {
Console.WriteLine("Hello, World!");
}
}```
6 changes: 6 additions & 0 deletions cogs/helloworld/erlang.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```erlang
-module(hello).
-export([hello_world/0]).

hello_world() -> io:fwrite("hello, world\n").
```
7 changes: 7 additions & 0 deletions cogs/helloworld/go.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
```
3 changes: 3 additions & 0 deletions cogs/helloworld/haskell.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```haskell
putStrLn "Hello, World!"
```
2 changes: 1 addition & 1 deletion cogs/helloworld/java.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ public class Main {
System.out.prinlnt("Hello, World!");
}
}
```
```
3 changes: 3 additions & 0 deletions cogs/helloworld/javascript.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```js
console.log("Hello World");
```
3 changes: 3 additions & 0 deletions cogs/helloworld/julia.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```julia
println("hello world")
```
5 changes: 5 additions & 0 deletions cogs/helloworld/lisp.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
```lisp
; LISP
(DEFUN HELLO-WORLD ()
(PRINT (LIST 'HELLO 'WORLD)))
```
3 changes: 3 additions & 0 deletions cogs/helloworld/lua.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```lua
print("Hello World")
```
11 changes: 11 additions & 0 deletions cogs/helloworld/objectivec.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```objectivec
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}
```
6 changes: 6 additions & 0 deletions cogs/helloworld/pascal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```pascal
program Hello;
begin
writeln ('Hello, world.');
end.
```
3 changes: 3 additions & 0 deletions cogs/helloworld/perl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```perl
print "Hello, World!\n";
```
3 changes: 3 additions & 0 deletions cogs/helloworld/php.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```php
echo('Hello, World!');
```
2 changes: 1 addition & 1 deletion cogs/helloworld/python.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
```python
print("Hello, World!")
```
```
3 changes: 3 additions & 0 deletions cogs/helloworld/ruby.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```ruby
puts "Hello, World!"
```
2 changes: 1 addition & 1 deletion cogs/helloworld/rust.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
fn main() {
println!("Hello, World!");
}
```
```
7 changes: 7 additions & 0 deletions cogs/helloworld/scala.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```scala
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}
```
3 changes: 3 additions & 0 deletions cogs/helloworld/swift.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```swift
print("Hello, World!")
```
Loading

0 comments on commit 06ecf1c

Please sign in to comment.