Skip to content

Commit

Permalink
Merge pull request #6 from Atelier-Epita/docs-and-close
Browse files Browse the repository at this point in the history
Added issue and thread closing
  • Loading branch information
thibaultjunin authored Feb 7, 2023
2 parents cef2843 + db16689 commit dee0f84
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 29 deletions.
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,20 @@ cp .env.example .env
Then add in your tokens for discord and github.
be carefull to not push those tokens to github.

### add the service
### Deploy

```bash
systemctl enable orderbot.service
systemctl start orderbot.service
```
<!-- TODO -->

## Usage

Once the bot is running, it will listen to discord channels.
When the :thread: reaction is added to a message, it will create a new thread on discord and a new issue on github. The issue number will be added to the thread name.
Then, when a message is sent in the thread, it will be added as a comment to the issue, this way, the whole conversation is kept in the issue.

*Note: for older threads (before the bot was deployed), you can rename the thread to add the issue number at the end of the name. Only the new messages will be added as comments to the issue.*

### Commands (only available to admins)

- `!ping` : pong.
- `!close` : close the thread and the issue.
- `!help` : display the available commands.
2 changes: 2 additions & 0 deletions orderbot/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
import sys

from dotenv import load_dotenv

Expand All @@ -9,6 +10,7 @@
logging.basicConfig(
handlers=[
logging.FileHandler("orderbot.log", mode="w"),
logging.StreamHandler(sys.stdout)
],
format='[%(asctime)s][%(levelname)s][%(message)s]',
datefmt='%d-%b-%y %H:%M:%S',
Expand Down
70 changes: 48 additions & 22 deletions orderbot/src/discord_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

class DiscordBot(discord.Client):
COMMANDS = {
"!ping": lambda message, args: message.channel.send("Pong!"),
"!ping": lambda self, message: self.on_ping(message),
"!close": lambda self, message: self.on_close(message),
"!help": lambda self, message: self.on_help(message),
}

def __init__(self, token, github_bot: GithubBot):
Expand All @@ -20,22 +22,49 @@ def __init__(self, token, github_bot: GithubBot):
def run(self):
super().run(self.token)

def repr_message(self, message):
return f"Message: {message.content} from {message.author} in {message.channel} at {message.created_at} with {message.reactions} reactions"
def repr_message(self, message: discord.Message):
# remove emojis
return f"Message: {message.content} from {message.author} in {message.channel} at {message.created_at} with {message.reactions} reactions".encode("ascii", "ignore").decode()

async def create_thread_issue(self, message):
async def on_ping(self, message: discord.Message):
message.channel.send("Pong!")

async def on_close(self, message: discord.Message):
thread = message.channel
assert type(thread) == discord.Thread

# try to get issue number from thread name
issue_number = thread.name.split("#")[-1]
if issue_number.isnumeric():
issue_number = int(issue_number)
await thread.send(f"Closing issue #{issue_number}")
await self.github_bot.add_issue_comment(issue_number, f"Issue closed by {message.author}")
await self.github_bot.close_issue(issue_number)

else:
await thread.send("Could not find issue number in thread name")
logging.error(f"Could not find issue number in thread name {thread.name}")

# archive thread
await thread.send("Closing thread")
await thread.edit(archived=True, locked=True)

async def on_help(self, message):
message.channel.send("Commands: " + ", ".join(self.COMMANDS.keys()))

async def on_ready(self, *args, **kwargs):
logging.info(f"We have logged in as {self.user}")

async def create_thread_issue(self, message: discord.Message):
# create a new issue on github
issue = await self.github_bot.create_issue(f"{message.channel.name} - {message.author.display_name}", f"[{message.author}]" + message.content, os.getenv("GITHUB_PROJECT_NUMBER"))

# create thread
issue_number = issue["createIssue"]["issue"]["number"]
thread = await message.create_thread(name=f"{message.author.display_name} #{issue.number}")
# await thread.send("Issue created, please wait for a staff member to respond")

logging.info(f"Created issue #{issue_number} for {message.author} in {message.channel.name}")

async def on_ready(self, *args, **kwargs):
logging.info(f"We have logged in as {self.user}")
logging.info(
f"Created issue #{issue_number} for {message.author} in {message.channel.name}")

async def on_message(self, message: discord.Message):
logging.debug(self.repr_message(message))
Expand All @@ -44,36 +73,33 @@ async def on_message(self, message: discord.Message):
if message.author == self.user:
return

# only reply to authorized users (to be defined later)
if "Bureau" not in [r.name for r in message.author.roles]:
return
channel_name = message.channel.name

# check if the message is a command
if message.content.startswith("!"):

# only reply to authorized users (to be defined later)
if "Bureau" not in [r.name for r in message.author.roles]:
await message.channel.send("You are not authorized to use this command")
return

# split the message into command and arguments
command = message.content.split(" ")[0]
args = message.content.split(" ")[1:]
channel = message.channel.name

# check if the command is valid
if command in DiscordBot.COMMANDS:
# execute the command
await DiscordBot.COMMANDS[command](message, args)
await DiscordBot.COMMANDS[command](self, message, *args)

else:
# send an error message
await message.channel.send("Invalid command")

channel = message.channel.name
if "#" in channel:
issue_number = int(channel.split("#")[-1])
elif "#" in channel_name:
issue_number = int(channel_name.split("#")[-1])
await self.github_bot.add_issue_comment(issue_number, f"[{message.author}] - {message.content}")

# on reaction
async def on_message_edit(self, before, after):
logging.debug(f"Message edited: {before} -> {after}")
await self.on_message(after)

async def on_raw_reaction_add(self, payload):
reaction = payload.emoji
channel = self.get_channel(payload.channel_id)
Expand Down
33 changes: 31 additions & 2 deletions orderbot/src/github_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ async def add_issue_comment(self, number, body):
issue = await self.fetch_issue_by_number(self.repo, number)
issue_id = issue["organization"]["repository"]["issue"]["id"]
except KeyError:
logging.error("Issue not found")
logging.error(f"Issue {number} not found")
return

# add the comment to the issue
Expand All @@ -232,4 +232,33 @@ async def add_issue_comment(self, number, body):
)

logging.info(f"Added Github comment: {body} in issue {number}")
return comment
return comment

async def close_issue(self, number):
try:
issue = await self.fetch_issue_by_number(self.repo, number)
issue_id = issue["organization"]["repository"]["issue"]["id"]
except KeyError:
logging.error(f"Issue {number} not found")
return

# close the issue
query = gql(
"""
mutation ($issueId: ID!) {
closeIssue(input: {issueId: $issueId}) {
clientMutationId
}
}
"""
)

close = await self.client.execute_async(
query,
variable_values={
"issueId": issue_id,
}
)

logging.info(f"Closed issue {number}")
return close

0 comments on commit dee0f84

Please sign in to comment.