Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ctfnote setup to config file #12

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ Some planned/wanted features include
- [ ] Manage a calendar of upcoming contests to see who is interested in a particular CTF, and how much tryharding there will or should be
- [ ] Team- and individual-based opt-in and opt-out
- [ ] ctfnote integration
- [x] specify server settings with `/ctfnote_update_auth` (can be done by player)
- [x] create a ctfnote pad for a `/chal` (can be done by player)
- [x] Takes an optional argument for concurrent ctfs.
- [x] pin ctfnote link to the channel
Expand Down Expand Up @@ -75,8 +74,6 @@ Currently in development by:
docker run --rm -it orgzbot:latest
```

* in the discord server, specify the ctfnote credentials with the `/ctfnote_update_auth` command. If you don't want to use it, set it to something invalid i guess...

## CTFNote Integration

*Information about the internal assumptions used. This should only be relevant when you change the code.*
Expand Down
7 changes: 6 additions & 1 deletion config.sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
"keyID": "key_id"
},
"archive": {
"url": "https://example.com/",
"url": "https://archive.example.com/",
"secret": "hex-encoded secret"
},
"ctfnote": {
"url": "https://ctfnote.example.com/",
"admin_login": "admin_login",
"admin_pass": "admin_pass"
}
}
23 changes: 0 additions & 23 deletions organizers_bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,29 +216,6 @@ async def nuke(ctx: discord_slash.SlashContext, category: discord.abc.GuildChann
await category.delete(reason=f"Nuked by {ctx.author.name}")
await ctx.send(f"Category {category.name} was nuked on request of {ctx.author.name}", hidden=False)



@slash.slash(name="ctfnote_update_auth",
description="Update url and auth login info for the ctfnote integration",
guild_ids=[config.bot.guild],
options=[
create_option(name="url",
description="The url ctfnote is hosted at",
option_type=SlashCommandOptionType.STRING,
required=True),
create_option(name="adminlogin",
description="Admin login password",
option_type=SlashCommandOptionType.STRING,
required=True),
create_option(name="adminpass",
description="Admin login password",
option_type=SlashCommandOptionType.STRING,
required=True)
])
@require_role(config.mgmt.player_role)
async def ctfnote_update_auth(ctx: discord_slash.SlashContext, url:str, adminlogin:str, adminpass:str):
await ctfnote.update_login_info(ctx, url, adminlogin, adminpass)

@slash.slash(name="ctfnote_assign_lead",
description="Assign given player as challenge lead for this channel",
guild_ids=[config.bot.guild],
Expand Down
14 changes: 13 additions & 1 deletion organizers_bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ class ArchiveConfig:
url: str
secret: bytes

@dataclasses.dataclass
class CtfNoteConfig:
url: str
admin_login: str
admin_pass: str

def load(filename: pathlib.Path):
global is_loaded, bot, mgmt, s3, archive
global is_loaded, bot, mgmt, s3, archive, ctfnote
with filename.open("r") as configfile:
conf = json.load(configfile)
bot = BotConfig(
Expand All @@ -55,6 +61,11 @@ def load(filename: pathlib.Path):
conf['archive']['url'],
bytes.fromhex(conf['archive']['secret']),
)
ctfnote = CtfNoteConfig(
conf['ctfnote']['url'],
conf['ctfnote']['admin_login'],
conf['ctfnote']['admin_pass'],
)
is_loaded = True

logging.basicConfig(level=logging.INFO)
Expand All @@ -63,3 +74,4 @@ def load(filename: pathlib.Path):
mgmt: ManagementConfig
s3: S3Config
archive: ArchiveConfig
ctfnote: CtfNoteConfig
53 changes: 9 additions & 44 deletions organizers_bot/ctfnote.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import logging
import asyncio
from . import queries
from . import config
import discord
import discord_slash # type: ignore
import json
Expand Down Expand Up @@ -465,18 +466,13 @@ async def start_listening(subscription, name):
loop.create_task(start_listening(queries.subscribe_to_task, "task_event"))


# These credentials can be changed with a bot command
# URL _must_ end with a slash
URL = "https://cyanpencil.xyz/note/"
admin_login = "a"
admin_pass = "b"
ctfnote: CTFNote = CTFNote("")
enabled: bool = False
enabled: bool = True

async def login():
global ctfnote
ctfnote = CTFNote(URL + "graphql")
await ctfnote.login(admin_login, admin_pass)
ctfnote = CTFNote(config.ctfnote.url + "graphql")
await ctfnote.login(config.ctfnote.admin_login, config.ctfnote.admin_pass)

async def refresh_ctf(ctx: discord_slash.SlashContext, ctfid: int = None):
"""
Expand Down Expand Up @@ -524,37 +520,6 @@ async def refresh_ctf(ctx: discord_slash.SlashContext, ctfid: int = None):
# Just one current ctf is happening.
return CTF(ctfnote.client, current_ctfs[0])

async def update_login_info(ctx: discord_slash.SlashContext, URL_:str, admin_login_:str, admin_pass_:str):
global URL, admin_pass, admin_login, enabled
URL = URL_

# option to completely disable ctfnote interactions until login infos are updated again.
if 'disable' == URL.lower() or 'disabled' == URL.lower() or '' == URL.lower():
enabled = False
await ctx.send("Disabled CTFNote integration.", hidden=False)
return
await ctx.defer(hidden=True)

if not URL.endswith('/'):
URL = f"{URL}/"
admin_pass = admin_pass_
admin_login = admin_login_
try:
await login()
#except gql.transport.aiohttp.client_exceptions.InvalidURL as e:
# I tried to be specific but it only exists once it crashes...
except Exception as e:
await ctx.send("No ctfnote for you. Can't reach the site or something.", hidden=True)
enabled = False
print(e)
return

# Test whether it worked
current_ctfs = await ctfnote.getActiveCtfs()
if current_ctfs is not None and ctfnote.token is not None:
enabled = True
await ctx.send("Success.", hidden=True)

async def update_flag(ctx: discord_slash.SlashContext, flag: str):
"""
Updates the flag on ctfnote. To unset, simply set `flag` to the empty string.
Expand Down Expand Up @@ -596,8 +561,8 @@ async def add_task(ctx: discord_slash.SlashContext, created, name: str,
if ctx is not None:
# discord trick: <URL> does not show link previews, while URL does
ctfnote_url = "\nctfnote url: " + \
f"<{URL}#/ctf/{current_ctf.id}-{slugify(current_ctf.name)}/task/{result.id}-{slugify(result.title)}>"
hackmd_url = "\nhackmd (in case the other is broken): " + f"<{URL}{result.url}>"
f"<{config.ctfnote.url}#/ctf/{current_ctf.id}-{slugify(current_ctf.name)}/task/{result.id}-{slugify(result.title)}>"
hackmd_url = "\nhackmd (in case the other is broken): " + f"<{config.ctfnote.url}{result.url}>"
# we need to save the ctf id somewhere to distinguish between concurrent ctfs.
# Note: the pinned message is identified by containing the word "botdb" and "ctfnote url:".
botdb = json.dumps({
Expand Down Expand Up @@ -679,7 +644,7 @@ async def fixup_task(ctx: discord_slash.SlashContext,
"""
await ctx.defer(hidden=True)
if not enabled:
await ctx.send("Please enable ctfnote integration first. By specifying valid admin credentials with /ctfnote_update_auth.")
await ctx.send("Please enable ctfnote integration first.")
return
prev_pinned_msg = await get_pinned_ctfnote_message(ctx)
reply_text = "Done."
Expand Down Expand Up @@ -752,15 +717,15 @@ async def import_ctf_from_ctftime(ctx: discord_slash.SlashContext, ctftime_link_
return None

if response.get('importCtf',False) == "Already present":
await ctx.send(f"That ctf already exists. Check it in the dashboard(<{URL}>).", hidden=hide)
await ctx.send(f"That ctf already exists. Check it in the dashboard(<{config.ctfnote.url}>).", hidden=hide)
return

# TODO: it would be nice to receive the details of the ctf that was just imported.
# Especially the ctfnote CTF id for use as optional argument of the /chal command.
# But that would require the server to actually return it... or to loop over all (incoming?) ctfs.

#await ctx.send(f"Imported {response['title']} with weight {response['weight']} successfully. It has now id {response['id']}", hidden=hide)
await ctx.send(f"Successfully imported. It should show up in the dashboard(<{URL}>) after a page reload.", hidden=hide)
await ctx.send(f"Successfully imported. It should show up in the dashboard(<{config.ctfnote.url}>) after a page reload.", hidden=hide)

async def get_pinned_ctfnote_message(ctx: discord_slash.SlashContext):
"""
Expand Down