Merge branch 'master' into conquest_develop

conquest_develop
bobloy 4 years ago
commit 36d6e5c9bf

@ -17,8 +17,9 @@ Cog Function
| forcemention | **Alpha** | <details><summary>Mentions unmentionable roles</summary>Very simple cog, mention doesn't persist</details> | | forcemention | **Alpha** | <details><summary>Mentions unmentionable roles</summary>Very simple cog, mention doesn't persist</details> |
| hangman | **Beta** | <details><summary>Play a game of hangman</summary>Some visual glitches and needs more customization</details> | | hangman | **Beta** | <details><summary>Play a game of hangman</summary>Some visual glitches and needs more customization</details> |
| howdoi | **Incomplete** | <details><summary>Ask coding questions and get results from StackExchange</summary>Not yet functional</details> | | howdoi | **Incomplete** | <details><summary>Ask coding questions and get results from StackExchange</summary>Not yet functional</details> |
| leaver | **Beta** | <details><summary>Send a message in a channel when a user leaves the server</summary>Seems to be functional, please report any bugs or suggestions</details> |
| infochannel | **Beta** | <details><summary>Create a channel to display server info</summary>Just released, please report bugs</details> | | infochannel | **Beta** | <details><summary>Create a channel to display server info</summary>Just released, please report bugs</details> |
| launchlib | **Beta** | <details><summary>Access rocket launch data</summary>Just released, please report bugs</details> |
| leaver | **Beta** | <details><summary>Send a message in a channel when a user leaves the server</summary>Seems to be functional, please report any bugs or suggestions</details> |
| lovecalculator | **Alpha** | <details><summary>Calculate the love between two users</summary>[Snap-Ons] Just updated to V3</details> | | lovecalculator | **Alpha** | <details><summary>Calculate the love between two users</summary>[Snap-Ons] Just updated to V3</details> |
| lseen | **Alpha** | <details><summary>Track when a member was last online</summary>Alpha release, please report bugs</details> | | lseen | **Alpha** | <details><summary>Track when a member was last online</summary>Alpha release, please report bugs</details> |
| nudity | **Alpha** | <details><summary>Checks for NSFW images posted in non-NSFW channels</summary>Switched libraries, now functional</details> | | nudity | **Alpha** | <details><summary>Checks for NSFW images posted in non-NSFW channels</summary>Switched libraries, now functional</details> |

@ -3,7 +3,6 @@ import logging
import os import os
import pathlib import pathlib
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Literal
import discord import discord
from chatterbot import ChatBot from chatterbot import ChatBot
@ -14,9 +13,8 @@ from redbot.core import Config, commands
from redbot.core.commands import Cog from redbot.core.commands import Cog
from redbot.core.data_manager import cog_data_path from redbot.core.data_manager import cog_data_path
from redbot.core.utils.predicates import MessagePredicate from redbot.core.utils.predicates import MessagePredicate
from redbot.core.utils import AsyncIter
log = logging.getLogger("red.fox_v3.chat") log = logging.getLogger("red.fox_v3.chatter")
class ENG_LG: class ENG_LG:
@ -420,21 +418,18 @@ class Chatter(Cog):
for the message filtering for the message filtering
""" """
########### ###########
is_private = isinstance(message.channel, discord.abc.PrivateChannel)
# user_allowed check, will be replaced with self.bot.user_allowed or if len(message.content) < 2 or message.author.bot:
# something similar once it's added
user_allowed = True
if len(message.content) < 2 or is_private or not user_allowed or message.author.bot:
return return
if await self.bot.cog_disabled_in_guild(self, message.guild): guild: discord.Guild = getattr(message, "guild", None)
if await self.bot.cog_disabled_in_guild(self, guild):
return return
ctx: commands.Context = await self.bot.get_context(message) ctx: commands.Context = await self.bot.get_context(message)
if ctx.prefix is not None: if ctx.prefix is not None: # Probably unnecessary, we're in on_message_without_command
return return
########### ###########
@ -454,23 +449,8 @@ class Chatter(Cog):
# print("not mentioned") # print("not mentioned")
return return
author = message.author
guild: discord.Guild = message.guild
channel: discord.TextChannel = message.channel channel: discord.TextChannel = message.channel
# if author.id != self.bot.user.id:
# if guild is None:
# to_strip = "@" + channel.me.display_name + " "
# else:
# to_strip = "@" + guild.me.display_name + " "
# text = message.clean_content
# if not text.startswith(to_strip):
# return
# text = text.replace(to_strip, "", 1)
# A bit more aggressive, could remove two mentions
# Or might not work at all, since mentionables are pre-cleaned_content
message.content = message.content.replace(prefix, "", 1) message.content = message.content.replace(prefix, "", 1)
text = message.clean_content text = message.clean_content

@ -89,7 +89,7 @@ class ExclusiveRole(Cog):
to_remove = (member_set - role_set) - {member.guild.default_role.id} to_remove = (member_set - role_set) - {member.guild.default_role.id}
if to_remove and member_set & role_set: if to_remove and member_set & role_set:
to_remove = [discord.utils.get(member.guild.roles, id=id) for id in to_remove] to_remove = [discord.utils.get(member.guild.roles, id=r_id) for r_id in to_remove]
await member.remove_roles(*to_remove, reason="Exclusive roles") await member.remove_roles(*to_remove, reason="Exclusive roles")
@commands.Cog.listener() @commands.Cog.listener()

@ -0,0 +1,5 @@
from .launchlib import LaunchLib
def setup(bot):
bot.add_cog(LaunchLib(bot))

@ -0,0 +1,254 @@
countryISOMapping = {
"AFG": "AF",
"ALA": "AX",
"ALB": "AL",
"DZA": "DZ",
"ASM": "AS",
"AND": "AD",
"AGO": "AO",
"AIA": "AI",
"ATA": "AQ",
"ATG": "AG",
"ARG": "AR",
"ARM": "AM",
"ABW": "AW",
"AUS": "AU",
"AUT": "AT",
"AZE": "AZ",
"BHS": "BS",
"BHR": "BH",
"BGD": "BD",
"BRB": "BB",
"BLR": "BY",
"BEL": "BE",
"BLZ": "BZ",
"BEN": "BJ",
"BMU": "BM",
"BTN": "BT",
"BOL": "BO",
"BIH": "BA",
"BWA": "BW",
"BVT": "BV",
"BRA": "BR",
"VGB": "VG",
"IOT": "IO",
"BRN": "BN",
"BGR": "BG",
"BFA": "BF",
"BDI": "BI",
"KHM": "KH",
"CMR": "CM",
"CAN": "CA",
"CPV": "CV",
"CYM": "KY",
"CAF": "CF",
"TCD": "TD",
"CHL": "CL",
"CHN": "CN",
"HKG": "HK",
"MAC": "MO",
"CXR": "CX",
"CCK": "CC",
"COL": "CO",
"COM": "KM",
"COG": "CG",
"COD": "CD",
"COK": "CK",
"CRI": "CR",
"CIV": "CI",
"HRV": "HR",
"CUB": "CU",
"CYP": "CY",
"CZE": "CZ",
"DNK": "DK",
"DJI": "DJ",
"DMA": "DM",
"DOM": "DO",
"ECU": "EC",
"EGY": "EG",
"SLV": "SV",
"GNQ": "GQ",
"ERI": "ER",
"EST": "EE",
"ETH": "ET",
"FLK": "FK",
"FRO": "FO",
"FJI": "FJ",
"FIN": "FI",
"FRA": "FR",
"GUF": "GF",
"PYF": "PF",
"ATF": "TF",
"GAB": "GA",
"GMB": "GM",
"GEO": "GE",
"DEU": "DE",
"GHA": "GH",
"GIB": "GI",
"GRC": "GR",
"GRL": "GL",
"GRD": "GD",
"GLP": "GP",
"GUM": "GU",
"GTM": "GT",
"GGY": "GG",
"GIN": "GN",
"GNB": "GW",
"GUY": "GY",
"HTI": "HT",
"HMD": "HM",
"VAT": "VA",
"HND": "HN",
"HUN": "HU",
"ISL": "IS",
"IND": "IN",
"IDN": "ID",
"IRN": "IR",
"IRQ": "IQ",
"IRL": "IE",
"IMN": "IM",
"ISR": "IL",
"ITA": "IT",
"JAM": "JM",
"JPN": "JP",
"JEY": "JE",
"JOR": "JO",
"KAZ": "KZ",
"KEN": "KE",
"KIR": "KI",
"PRK": "KP",
"KOR": "KR",
"KWT": "KW",
"KGZ": "KG",
"LAO": "LA",
"LVA": "LV",
"LBN": "LB",
"LSO": "LS",
"LBR": "LR",
"LBY": "LY",
"LIE": "LI",
"LTU": "LT",
"LUX": "LU",
"MKD": "MK",
"MDG": "MG",
"MWI": "MW",
"MYS": "MY",
"MDV": "MV",
"MLI": "ML",
"MLT": "MT",
"MHL": "MH",
"MTQ": "MQ",
"MRT": "MR",
"MUS": "MU",
"MYT": "YT",
"MEX": "MX",
"FSM": "FM",
"MDA": "MD",
"MCO": "MC",
"MNG": "MN",
"MNE": "ME",
"MSR": "MS",
"MAR": "MA",
"MOZ": "MZ",
"MMR": "MM",
"NAM": "NA",
"NRU": "NR",
"NPL": "NP",
"NLD": "NL",
"ANT": "AN",
"NCL": "NC",
"NZL": "NZ",
"NIC": "NI",
"NER": "NE",
"NGA": "NG",
"NIU": "NU",
"NFK": "NF",
"MNP": "MP",
"NOR": "NO",
"OMN": "OM",
"PAK": "PK",
"PLW": "PW",
"PSE": "PS",
"PAN": "PA",
"PNG": "PG",
"PRY": "PY",
"PER": "PE",
"PHL": "PH",
"PCN": "PN",
"POL": "PL",
"PRT": "PT",
"PRI": "PR",
"QAT": "QA",
"REU": "RE",
"ROU": "RO",
"RUS": "RU",
"RWA": "RW",
"BLM": "BL",
"SHN": "SH",
"KNA": "KN",
"LCA": "LC",
"MAF": "MF",
"SPM": "PM",
"VCT": "VC",
"WSM": "WS",
"SMR": "SM",
"STP": "ST",
"SAU": "SA",
"SEN": "SN",
"SRB": "RS",
"SYC": "SC",
"SLE": "SL",
"SGP": "SG",
"SVK": "SK",
"SVN": "SI",
"SLB": "SB",
"SOM": "SO",
"ZAF": "ZA",
"SGS": "GS",
"SSD": "SS",
"ESP": "ES",
"LKA": "LK",
"SDN": "SD",
"SUR": "SR",
"SJM": "SJ",
"SWZ": "SZ",
"SWE": "SE",
"CHE": "CH",
"SYR": "SY",
"TWN": "TW",
"TJK": "TJ",
"TZA": "TZ",
"THA": "TH",
"TLS": "TL",
"TGO": "TG",
"TKL": "TK",
"TON": "TO",
"TTO": "TT",
"TUN": "TN",
"TUR": "TR",
"TKM": "TM",
"TCA": "TC",
"TUV": "TV",
"UGA": "UG",
"UKR": "UA",
"ARE": "AE",
"GBR": "GB",
"USA": "US",
"UMI": "UM",
"URY": "UY",
"UZB": "UZ",
"VUT": "VU",
"VEN": "VE",
"VNM": "VN",
"VIR": "VI",
"WLF": "WF",
"ESH": "EH",
"YEM": "YE",
"ZMB": "ZM",
"ZWE": "ZW",
"XKX": "XK",
}
def country_mapping(countrycode):
return countryISOMapping[countrycode]

@ -0,0 +1,20 @@
{
"author": [
"Bobloy"
],
"min_bot_version": "3.4.0",
"description": "Pull information from the Launch Library API for space flights",
"hidden": false,
"install_msg": "Thank you for installing LaunchLib. Get started with `[p]load launchlib`, then `[p]help LaunchLib`",
"short": "Access launch data for space flights",
"end_user_data_statement": "This cog does not store any End User Data",
"requirements": ["python-launch-library"],
"tags": [
"bobloy",
"utils",
"launch",
"space",
"api",
"library"
]
}

@ -0,0 +1,130 @@
import asyncio
import functools
import logging
import discord
import launchlibrary as ll
from redbot.core import Config, commands
from redbot.core.bot import Red
from launchlib.countrymapper import country_mapping
log = logging.getLogger("red.fox_v3.launchlib")
class LaunchLib(commands.Cog):
"""
Cog Description
Less important information about the cog
"""
def __init__(self, bot: Red):
super().__init__()
self.bot = bot
self.config = Config.get_conf(self, identifier=0, force_registration=True)
default_guild = {}
self.config.register_guild(**default_guild)
self.api = ll.Api()
async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete"""
return
async def _embed_launch_data(self, launch: ll.Launch):
status: ll.LaunchStatus = launch.get_status()
rocket: ll.Rocket = launch.rocket
title = launch.name
description = status.description
urls = launch.vid_urls + launch.info_urls
if not urls and rocket:
urls = rocket.info_urls + [rocket.wiki_url]
if urls:
url = urls[0]
else:
url = None
color = discord.Color.green() if status.id in [1, 3] else discord.Color.red()
em = discord.Embed(title=title, description=description, url=url, color=color)
if rocket and rocket.image_url and rocket.image_url != "Array":
em.set_image(url=rocket.image_url)
agency = getattr(launch, "agency", None)
if agency is not None:
em.set_author(
name=agency.name,
url=agency.wiki_url,
icon_url=f"https://www.countryflags.io/{country_mapping(agency.country_code)}/flat/64.png",
)
field_options = [
("failreason", "Fail Reason"),
("holdreason", "Hold Reason"),
("id", "ID"),
("hashtag", "Hashtag"),
]
for f in field_options:
data = getattr(launch, f[0], None)
if data is not None and data:
em.add_field(name=f[1], value=data)
if launch.missions:
field_options = [
("description", "Mission Description"),
("typeName", "Mission Type"),
("name", "Mission Name"),
]
for mission in launch.missions:
for f in field_options:
data = mission.get(f[0], None)
if data is not None and data:
em.add_field(name=f[1], value=data)
if rocket and rocket.family:
em.add_field(name="Rocket Family", value=rocket.family)
em.timestamp = launch.windowstart
em.set_footer()
return em
@commands.group()
async def launchlib(self, ctx: commands.Context):
if ctx.invoked_subcommand is None:
pass
@launchlib.command()
async def next(self, ctx: commands.Context, num_launches: int = 1):
# launches = await api.async_next_launches(num_launches)
loop = asyncio.get_running_loop()
launches = await loop.run_in_executor(
None, functools.partial(self.api.fetch_launch, num=num_launches)
)
# launches = self.api.fetch_launch(num=num_launches)
print(len(launches))
async with ctx.typing():
for x, launch in enumerate(launches):
if x >= num_launches:
return
em = await self._embed_launch_data(launch)
if em is not None:
try:
await ctx.send(embed=em)
except discord.HTTPException:
await ctx.send(str(launch))
log.exception("Failed to send embed")
await asyncio.sleep(2)

@ -4,7 +4,7 @@ from datetime import datetime, timedelta
import discord import discord
from redbot.core import Config, checks, commands from redbot.core import Config, checks, commands
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.commands import Cog from redbot.core.commands import Cog, parse_timedelta
from redbot.core.utils.chat_formatting import pagify from redbot.core.utils.chat_formatting import pagify
@ -20,7 +20,7 @@ class Timerole(Cog):
self.config.register_global(**default_global) self.config.register_global(**default_global)
self.config.register_guild(**default_guild) self.config.register_guild(**default_guild)
self.updating = self.bot.loop.create_task(self.check_day()) self.updating = asyncio.create_task(self.check_day())
async def red_delete_data_for_user(self, **kwargs): async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete""" """Nothing to delete"""
@ -40,7 +40,7 @@ class Timerole(Cog):
""" """
await self.timerole_update() await self.timerole_update()
await ctx.send("Success") await ctx.tick()
@commands.group() @commands.group()
@checks.mod_or_permissions(administrator=True) @checks.mod_or_permissions(administrator=True)
@ -52,23 +52,34 @@ class Timerole(Cog):
@timerole.command() @timerole.command()
async def addrole( async def addrole(
self, ctx: commands.Context, role: discord.Role, days: int, *requiredroles: discord.Role self, ctx: commands.Context, role: discord.Role, time: str, *requiredroles: discord.Role
): ):
"""Add a role to be added after specified time on server""" """Add a role to be added after specified time on server"""
guild = ctx.guild guild = ctx.guild
to_set = {"days": days, "remove": False} try:
parsed_time = parse_timedelta(time, allowed_units=["weeks", "days", "hours"])
except commands.BadArgument:
await ctx.maybe_send_embed("Error: Invalid time string.")
return
days = parsed_time.days
hours = parsed_time.seconds // 60 // 60
to_set = {"days": days, "hours": hours, "remove": False}
if requiredroles: if requiredroles:
to_set["required"] = [r.id for r in requiredroles] to_set["required"] = [r.id for r in requiredroles]
await self.config.guild(guild).roles.set_raw(role.id, value=to_set) await self.config.guild(guild).roles.set_raw(role.id, value=to_set)
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
"Time Role for {0} set to {1} days until added".format(role.name, days) "Time Role for {0} set to {1} days and {2} hours until added".format(
role.name, days, hours
)
) )
@timerole.command() @timerole.command()
async def removerole( async def removerole(
self, ctx: commands.Context, role: discord.Role, days: int, *requiredroles: discord.Role self, ctx: commands.Context, role: discord.Role, time: str, *requiredroles: discord.Role
): ):
""" """
Add a role to be removed after specified time on server Add a role to be removed after specified time on server
@ -76,14 +87,24 @@ class Timerole(Cog):
Useful with an autorole cog Useful with an autorole cog
""" """
guild = ctx.guild guild = ctx.guild
try:
parsed_time = parse_timedelta(time, allowed_units=["weeks", "days", "hours"])
except commands.BadArgument:
await ctx.maybe_send_embed("Error: Invalid time string.")
return
to_set = {"days": days, "remove": True} days = parsed_time.days
hours = parsed_time.seconds // 60 // 60
to_set = {"days": days, "hours": hours, "remove": True}
if requiredroles: if requiredroles:
to_set["required"] = [r.id for r in requiredroles] to_set["required"] = [r.id for r in requiredroles]
await self.config.guild(guild).roles.set_raw(role.id, value=to_set) await self.config.guild(guild).roles.set_raw(role.id, value=to_set)
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
"Time Role for {0} set to {1} days until removed".format(role.name, days) "Time Role for {0} set to {1} days and {2} hours until removed".format(
role.name, days, hours
)
) )
@timerole.command() @timerole.command()
@ -174,7 +195,7 @@ class Timerole(Cog):
await member.add_roles(role, reason="Timerole") await member.add_roles(role, reason="Timerole")
else: else:
await member.remove_roles(role, reason="Timerole") await member.remove_roles(role, reason="Timerole")
except discord.Forbidden: except (discord.Forbidden, discord.NotFound) as e:
results += "{} : {} **(Failed)**\n".format(member.display_name, role.name) results += "{} : {} **(Failed)**\n".format(member.display_name, role.name)
else: else:
results += "{} : {}\n".format(member.display_name, role.name) results += "{} : {}\n".format(member.display_name, role.name)
@ -192,7 +213,11 @@ class Timerole(Cog):
continue continue
if ( if (
member.joined_at + timedelta(days=role_dict[str(role_id)]["days"]) member.joined_at
+ timedelta(
days=role_dict[str(role_id)]["days"],
hours=role_dict[str(role_id)].get("hours", 0),
)
<= datetime.today() <= datetime.today()
): ):
# Qualifies # Qualifies
@ -201,4 +226,4 @@ class Timerole(Cog):
async def check_day(self): async def check_day(self):
while self is self.bot.get_cog("Timerole"): while self is self.bot.get_cog("Timerole"):
await self.timerole_update() await self.timerole_update()
await asyncio.sleep(86400) await asyncio.sleep(3600)

Loading…
Cancel
Save