1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 19:44:20 +00:00

it... works? surprisingly?

This commit is contained in:
Steffo 2019-11-20 01:55:04 +01:00
parent a5ff59779a
commit 3feca93486
8 changed files with 121 additions and 28 deletions

View file

@ -47,8 +47,9 @@ def run(telegram: typing.Optional[bool],
royalnet_log: Logger = getLogger("royalnet") royalnet_log: Logger = getLogger("royalnet")
royalnet_log.setLevel(log_level) royalnet_log.setLevel(log_level)
stream_handler = StreamHandler() stream_handler = StreamHandler()
stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {levelname}\t| {message}", style="{") stream_handler.formatter = Formatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t| {message}", style="{")
royalnet_log.addHandler(stream_handler) royalnet_log.addHandler(stream_handler)
royalnet_log.debug("Logging: ready")
def get_secret(username: str): def get_secret(username: str):
return keyring.get_password(f"Royalnet/{secrets_name}", username) return keyring.get_password(f"Royalnet/{secrets_name}", username)
@ -141,7 +142,8 @@ def run(telegram: typing.Optional[bool],
'commands': enabled_commands, 'commands': enabled_commands,
'events': enabled_events, 'events': enabled_events,
'herald_config': herald_config.copy(name="telegram"), 'herald_config': herald_config.copy(name="telegram"),
'secrets_name': secrets_name 'secrets_name': secrets_name,
'log_level': log_level,
} }
telegram_process = multiprocessing.Process(name="Telegram Serf", telegram_process = multiprocessing.Process(name="Telegram Serf",
target=r.serf.telegram.TelegramSerf.run_process, target=r.serf.telegram.TelegramSerf.run_process,
@ -163,7 +165,8 @@ def run(telegram: typing.Optional[bool],
'commands': enabled_commands, 'commands': enabled_commands,
'events': enabled_events, 'events': enabled_events,
'herald_config': herald_config.copy(name="discord"), 'herald_config': herald_config.copy(name="discord"),
'secrets_name': secrets_name 'secrets_name': secrets_name,
'log_level': log_level,
} }
discord_process = multiprocessing.Process(name="Discord Serf", discord_process = multiprocessing.Process(name="Discord Serf",
target=r.serf.discord.DiscordSerf.run_process, target=r.serf.discord.DiscordSerf.run_process,
@ -181,6 +184,7 @@ def run(telegram: typing.Optional[bool],
'database_uri': alchemy_url, 'database_uri': alchemy_url,
'page_stars': enabled_page_stars, 'page_stars': enabled_page_stars,
'exc_stars': enabled_exception_stars, 'exc_stars': enabled_exception_stars,
'log_level': log_level,
} }
constellation_process = multiprocessing.Process(name="Constellation", constellation_process = multiprocessing.Process(name="Constellation",
target=r.constellation.Constellation.run_process, target=r.constellation.Constellation.run_process,

View file

@ -28,9 +28,11 @@ class SummonCommand(Command):
else: else:
member = None member = None
guild = None guild = None
try: name = args.joined()
# TODO: do something! response: dict = await self.interface.call_herald_event("discord", "summon", {
pass "channel_name": name,
except Exception as e: "guild_id": guild.id if guild is not None else None,
breakpoint() "user_id": member.id if member is not None else None,
await data.reply(f"✅ Connesso alla chat vocale.") })
await data.reply(f"✅ Connected to [b]#{response['channel']['name']}[/b]"
f" in [i]{response['channel']['guild']['name']}[/i]!")

View file

@ -1,9 +1,9 @@
# Imports go here! # Imports go here!
from .summon import SummonEvent
# Enter the commands of your Pack here! # Enter the commands of your Pack here!
available_events = [ available_events = [
SummonEvent,
] ]
# Don't change this, it should automatically generate __all__ # Don't change this, it should automatically generate __all__

View file

@ -0,0 +1,59 @@
from typing import Optional
from royalnet.commands import *
from royalnet.serf.discord import DiscordSerf
try:
import discord
except ImportError:
discord = None
class SummonEvent(Event):
name = "summon"
async def run(self, *, channel_name: str, guild_id: Optional[int], user_id: Optional[int], **kwargs):
if not isinstance(self.serf, DiscordSerf):
raise UnsupportedError("Summon can't be called on interfaces other than Discord.")
if discord is None:
raise UnsupportedError("'discord' extra is not installed.")
# Find the guild
if guild_id is not None:
guild: Optional["discord.Guild"] = self.serf.client.get_guild(guild_id)
else:
guild = None
# Find the member
if user_id is not None and guild is not None:
member = guild.get_member(user_id=user_id)
else:
member = None
# Find accessible_to
accessible_to = [self.serf.client.user]
if member is not None:
accessible_to.append(member)
# Find the channel
channel: Optional["discord.VoiceChannel"] = self.serf.find_channel(channel_type=discord.VoiceChannel,
name=channel_name,
guild=guild,
accessible_to=accessible_to,
required_permissions=["connect", "speak"])
if channel is None:
raise InvalidInputError("No channels found with the specified name.")
# Connect to the channel
await self.serf.voice_connect(channel)
# Find the created bard
bard = self.serf.bards[channel.guild]
bard_peek = await bard.peek()
# Reply to the request
return {
"channel": {
"id": channel.id,
"name": channel.name,
"guild": {
"name": channel.guild.name,
},
},
"bard": {
"type": bard.__class__.__qualname__,
"peek": bard_peek,
}
}

View file

@ -116,6 +116,7 @@ class Constellation:
database_uri: str, database_uri: str,
page_stars: typing.List[typing.Type[PageStar]] = None, page_stars: typing.List[typing.Type[PageStar]] = None,
exc_stars: typing.List[typing.Type[ExceptionStar]] = None, exc_stars: typing.List[typing.Type[ExceptionStar]] = None,
log_level: str = "WARNING",
*, *,
debug: bool = __debug__,): debug: bool = __debug__,):
"""Blockingly create and run the Constellation. """Blockingly create and run the Constellation.
@ -131,6 +132,16 @@ class Constellation:
exc_stars=exc_stars, exc_stars=exc_stars,
debug=debug) debug=debug)
# Initialize logging, as Windows doesn't have fork
royalnet_log: logging.Logger = logging.getLogger("royalnet")
royalnet_log.setLevel(log_level)
stream_handler = logging.StreamHandler()
stream_handler.formatter = logging.Formatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t| {message}",
style="{")
if len(royalnet_log.handlers) < 1:
royalnet_log.addHandler(stream_handler)
royalnet_log.debug("Logging: ready")
# Initialize Sentry on the process # Initialize Sentry on the process
if sentry_sdk is None: if sentry_sdk is None:
log.info("Sentry: not installed") log.info("Sentry: not installed")

View file

@ -160,12 +160,12 @@ class DiscordSerf(Serf):
await self.client.login(token) await self.client.login(token)
await self.client.connect() await self.client.connect()
async def find_channel(self, def find_channel(self,
channel_type: Optional[Type["discord.abc.GuildChannel"]] = None, channel_type: Optional[Type["discord.abc.GuildChannel"]] = None,
name: Optional[str] = None, name: Optional[str] = None,
guild: Optional["discord.Guild"] = None, guild: Optional["discord.Guild"] = None,
accessible_to: List["discord.User"] = None, accessible_to: List["discord.User"] = None,
required_permissions: List[str] = None) -> Optional["discord.abc.GuildChannel"]: required_permissions: List[str] = None) -> Optional["discord.abc.GuildChannel"]:
"""Find the best channel matching all requests. """Find the best channel matching all requests.
In case multiple channels match all requests, return the one with the most members connected. In case multiple channels match all requests, return the one with the most members connected.
@ -201,11 +201,11 @@ class DiscordSerf(Serf):
pass pass
ch_guild: "discord.Guild" = ch.guild ch_guild: "discord.Guild" = ch.guild
if ch.guild == ch_guild: if ch.guild != ch_guild:
continue continue
for user in accessible_to: for user in accessible_to:
member: "discord.Member" = guild.get_member(user.id) member: "discord.Member" = ch.guild.get_member(user.id)
if member is None: if member is None:
continue continue
permissions: "discord.Permissions" = ch.permissions_for(member) permissions: "discord.Permissions" = ch.permissions_for(member)

View file

@ -156,11 +156,22 @@ class Serf:
request: Request = Request(handler=event_name, data=args) request: Request = Request(handler=event_name, data=args)
response: Response = await self.herald.request(destination=destination, request=request) response: Response = await self.herald.request(destination=destination, request=request)
if isinstance(response, ResponseFailure): if isinstance(response, ResponseFailure):
# TODO: pretty sure there's a better way to do this
if response.extra_info["type"] == "CommandError": if response.extra_info["type"] == "CommandError":
raise CommandError(response.extra_info["message"]) raise CommandError(response.extra_info["message"])
# TODO: change exception type elif response.extra_info["type"] == "UserError":
raise Exception(f"Herald action call failed:\n" raise UserError(response.extra_info["message"])
f"[p]{response}[/p]") elif response.extra_info["type"] == "InvalidInputError":
raise InvalidInputError(response.extra_info["message"])
elif response.extra_info["type"] == "UnsupportedError":
raise UnsupportedError(response.extra_info["message"])
elif response.extra_info["type"] == "ConfigurationError":
raise ConfigurationError(response.extra_info["message"])
elif response.extra_info["type"] == "ExternalError":
raise ExternalError(response.extra_info["message"])
else:
raise TypeError(f"Herald action call returned invalid error:\n"
f"[p]{response}[/p]")
elif isinstance(response, ResponseSuccess): elif isinstance(response, ResponseSuccess):
return response.data return response.data
else: else:
@ -233,8 +244,6 @@ class Serf:
response_data = await event.run(**message.data) response_data = await event.run(**message.data)
return ResponseSuccess(data=response_data) return ResponseSuccess(data=response_data)
except Exception as e: except Exception as e:
sentry_sdk.capture_exception(e)
log.error(f"Event error: {e.__class__.__qualname__} in {event.name}")
return ResponseFailure("exception_in_event", return ResponseFailure("exception_in_event",
f"An exception was raised in the event for '{message.handler}'.", f"An exception was raised in the event for '{message.handler}'.",
extra_info={ extra_info={
@ -290,8 +299,7 @@ class Serf:
await data.reply(f"⚠️ {e.message}") await data.reply(f"⚠️ {e.message}")
except Exception as e: except Exception as e:
self.sentry_exc(e) self.sentry_exc(e)
error_message = f"⛔ [b]{e.__class__.__name__}[/b]\n" \ error_message = f"⛔️ [b]{e.__class__.__name__}[/b]\n" + '\n'.join(e.args)
'\n'.join(e.args)
await data.reply(error_message) await data.reply(error_message)
async def run(self): async def run(self):
@ -300,12 +308,21 @@ class Serf:
# OVERRIDE THIS METHOD! # OVERRIDE THIS METHOD!
@classmethod @classmethod
def run_process(cls, *args, **kwargs): def run_process(cls, *args, log_level: str = "WARNING", **kwargs):
"""Blockingly create and run the Serf. """Blockingly create and run the Serf.
This should be used as the target of a :class:`multiprocessing.Process`.""" This should be used as the target of a :class:`multiprocessing.Process`."""
serf = cls(*args, **kwargs) serf = cls(*args, **kwargs)
royalnet_log: logging.Logger = logging.getLogger("royalnet")
royalnet_log.setLevel(log_level)
stream_handler = logging.StreamHandler()
stream_handler.formatter = logging.Formatter("{asctime}\t| {processName}\t| {levelname}\t| {name}\t| {message}",
style="{")
if len(royalnet_log.handlers) < 1:
royalnet_log.addHandler(stream_handler)
royalnet_log.debug("Logging: ready")
if sentry_sdk is None: if sentry_sdk is None:
log.info("Sentry: not installed") log.info("Sentry: not installed")
else: else:

View file

@ -196,7 +196,7 @@ class TelegramSerf(Serf):
else: else:
session = None session = None
# Prepare data # Prepare data
data = self.Data(interface=command.interface, session=session, loop=self.loop, message=message) data = self.Data(interface=command.interface, session=session, loop=self.loop, update=update)
# Call the command # Call the command
await self.call(command, data, parameters) await self.call(command, data, parameters)
# Close the alchemy session # Close the alchemy session