#dev-contrib

1 messages · Page 52 of 1

crude gyro
#

the 10% that aren't caught by the filters will be caught by normal, organic moderation

#

so by keeping the filters relatively simple and only catching obvious cases, we can keep the maintainability costs low, and the community doesn't really suffer for it.

uneven cairn
#

Ah, that makes sense

#

So should the bad name filter also include URL invites?

#

or is that also intended to be manually caught?

crude gyro
#

I don't think we've ever discussed it before, it's a perfectly valid question

#

<@&267629731250176001> <@&587606783669829632> Do you guys have an opinion on this? Should we be checking URLs for bad words?

glass pecan
#

urls would be way more commonly inaccurate to filter by word patterns that we use for general message content

crude gyro
#

can you give an example of what you mean?

nocturne hare
#

urls will probably give a lot of false positives for those randomly generated keys

glass pecan
#

sydneytherapist.com

crude gyro
#

right, so like hashes that contain faG or whatever

#

hahaha

nocturne hare
#

lol

glass pecan
#

these are a known issue due to lacking of spaces

crude gyro
nocturne hare
#

And yes, that's what i mean

#

We've had a few hashes trigger the filters already in code

crude gyro
#

yes, it happens.

nocturne hare
#

I'd imagine it's more common in urls

#

but then, I'm not against it

#

Pings don't hurt me.

glass pecan
#

i personally am for more personalised behaviour specific for urls

molten bough
#

Scunthorpe problem is notoriously hard to solve, yeah

glass pecan
#

like how we already have a link blacklist, in a simple sense

#

but also i'd like to see eventually maybe consideration for a url trust check

molten bough
#

There's web of trust, and maybe we could try to unfurl URLs in case they're shortened?

glass pecan
#

there's a service for that

#

there's also this

molten bough
#

lol, spoopy detector

crude gyro
#

I don't think a trust check for URLs is a terrible idea, sure.

woeful thorn
#

Pings don’t hurt, no, but a flurry of non-action pings tunes people out to ones that actually matter

glass pecan
crude gyro
#

let's stick this in an issue instead of a pin if we want it to happen

glass pecan
#

im trying to find another link first

#

i'll unpin once i do or someone else does

crude gyro
#

hey@uneven cairn, were you interested in working on something like this?

#

how about a trust check?

uneven cairn
#

Sure!

molten bough
#

page.rest is discontinued

#

I don't know of another unfurler service

uneven cairn
#

Would it also entail the url checks for invites?

#

Since those are easy to detect

glass pecan
#

i found this but i don't think it's the one that was suggested to me

crude gyro
#

trust checking invites?

#

I'm not sure I follow

uneven cairn
#

Oh no

molten bough
#

That'd work for major sites

#

I wonder if it's able to handle custom shorteners

uneven cairn
#

As in someone might try to put an unauthorised invite as their display name

#

like that

glass pecan
#

not sure gdude, but it would be interesting to check

#

that would be a simple regex check re: invites

crude gyro
#

seems like that would be a different issue, to me.

#

we already have an invite filter

#

expanding it to involve nicknames, well, that's an idea, I'm not entirely sold on it

glass pecan
#

yeah these would be specifically for checking unknown links

uneven cairn
#

Ah, alright

#

so this would just be an additional URL filter?

crude gyro
#

we don't want it to check every nickname on the server, or like, every time someone joins or every time someone changes nicknames or anything because with 40K users that's just a ton of stuff we don't care about

#

we only care about people who are active in this community, nobody will see the rest

molten bough
#

@glass pecan it is, yep

#

it does pick up on redirects and such, so it's not using arbitrary shortener APIs

crude gyro
#

I imagine that this would just be an expansion on the already existing URL filter

glass pecan
#

nice gdude

crude gyro
#

or maybe a new filter

glass pecan
#

thanks for checking

crude gyro
#

new filter could work

molten bough
uneven cairn
#

Oh, so that's why the nickname filtering triggers based on on_message.

crude gyro
#

yes exactly.

#

moderating inactive users is silly

#

but the nickname filter could probably, using the same on_message event, also be checking for invites and URLs

glass pecan
#

ill add these two to pins for quick reference until the issue is made

crude gyro
#

that would be a separate issue from the URL thing though

molten bough
#

That one looks great

crude gyro
#

you're welcome to handle both, @uneven cairn, if you're looking for stuff to do and you wanna carve out a spot for yourself in our filters.

#

but first things first - could you make some issues for these?

#

and include the millions of URL unfurling and trust check URLs @molten bough and @glass pecan have been posting above in the issue for the URL trust checker filter?

glass pecan
#

lol

crude gyro
#

and I guess it'll be up to you to do some research on them and figure out what will work well

uneven cairn
#

Sure

#

so one for web of trust-style filtering

molten bough
#

you're totally right to use an API for this by the way, I've written unfurlers and holy shit are there edge cases

glass pecan
#

yeah

#

i seriously don't want a custom implementation of these to maintain lol

crude gyro
#

yeah @uneven cairn and that one should probably unfurl shortened URLs, so that we're not trustchecking bitly

uneven cairn
#

So should URL unfurling and URL trust checking be separate issues?

molten bough
#

I expect you'd want to do unfurling first, since you probably want your trust check to be on the target

glass pecan
#

nah, the unfurling is to increase the effecti... what gdude said

#

im slow lol

uneven cairn
#

Right, that makes sense

molten bough
#

:>

#

actually you probably want to unfurl everything that doesn't match a url that we'd normally delete immediately

#

like an invite

#

and then run those filters over it again on the target

glass pecan
#

would just be a single url filter pipeline in the end

molten bough
#

I mean, if we ban a domain, and then someone posts a url from that domain that redirects elsewhere

#

if we don't check before and after unfurling then we're going to miss either the source (which we've banned) or the target

uneven cairn
#

I've made the issue now

#

although there is no explicit API policy

#

which makes me reluctant to use it, in case the API goes down

uneven cairn
#

Oh, nevermind

#

Completely missed the Docs tag

green oriole
#

How would you reschedule a task from within the this task, with the same ID?

#

It is for the offensive message PR, I need to reschedule deletion if it fails

#
bot.cogs.filtering | WARNING | Failed to delete message 695994391491248250, rescheduled for 2020-04-04 13:53:53.882000
bot.utils.scheduling | TRACE | Filtering: scheduling task #695994391491248250...
bot.utils.scheduling | DEBUG | Filtering: did not schedule task #695994391491248250; task was already scheduled.
bot.utils.scheduling | TRACE | Filtering: performing done callback for task #695994391491248250 140548982281216.
bot.utils.scheduling | TRACE | Filtering: deleting task #695994391491248250 140548982281216.```Here is the issue that I'm facing
tawdry vapor
#

Cancel the old task if it fails. Then, you will be able to schedule a new task.

green oriole
#

But can a task cancel itself?

tawdry vapor
#

Use asyncio.shield to prevent that

#

Yes, it can cancel itself

#

Put following code in a shield so it doesn't get cancelled

green oriole
#

Okay thanks!

tawdry vapor
#

Or just put the entire thing in a function and shield the function call

chilly elk
#

will it be possible for me to run docker on my windows 10 home? i appear to have Hyper-V capabilities

molten bough
#

You need Pro for docker iirc

#

Home includes just the parts of HyperV required for wsl2 from what I remember

sullen phoenix
#

yeah you'd need windows 10 pro for full virtualization

chilly elk
#

ah darn

#

so should I look into Docker Toolbox instead?

tawdry vapor
#

You could run a linux vm and then docker inside of that

#

That is what I do

#

A while ago I also considered looking into using vagrant + virtualbox and running docker inside that for a more headless approach but that never got anywhere

chilly elk
#

oh okay

#

do you have a recommendation for the linux vm?

tawdry vapor
#

You mean the distro, or like vmware vs virtualbox?

chilly elk
#

i guess both

#

im pretty inexperienced

tawdry vapor
#

I use vmware (paid version) + arch linux. I don't know what the free version of vmware is like. VirtualBox is free and open source, if that's your cup of tea. It doesn't really matter.

#

The distro doesn't matter either if you're going for something very minimal (i.e. it's job will be solely to run docker and nothing more)

#

I would not recommend Arch if you're not experienced with Linux

#

Maybe debian? IDK honestly

tough imp
#

i use virtualbox + ubuntu lts and works just fine

#

manjaro was giving me some trouble under virtualbox

#

interestingly on my other machine where i boot into linux directly manjaro is flawless while ubuntu was freezing

chilly elk
#

ok thanks so much

molten bough
#

You can run docker under WSL

#

I'm just not sure how well it handles it

chilly elk
#

hmm yeah thats the other thing i was thinking about

#

i might try virtualbox and see how it goes

chilly elk
#

sorry to bother people, but if I run docker on a vm will I also need to clone the github repo and install python on the vm as well? or can I somehow connect to docker inside the vm from outside

tawdry vapor
#

It is possible to connect from the host to the guest.

#

It depends on how you set up the network for the VM

#

I have mine in bridged mode, which means it gets its own IP and is considered separate from the host

#

So if a service in Docker is listener on localhost port 8080, and the VM has a local IP of 192.168.0.5, I can connect it from the host with 192.168.0.5:8080

chilly elk
#

oh okay, that makes sense

#

thanks

tawdry vapor
#

I have not used the other network modes but it seems it could just share with the host so it's all going to end up on localhost.

solemn birch
#

Hello

tawdry vapor
#

Hello

gusty sonnet
#

@cold moon yes? Is there any conflict?

cold moon
#

I show this on kick:

    @respect_role_hierarchy()
    async def apply_kick(self, ctx: Context, user: Member, reason: str, **kwargs) -> None:
        """Apply a kick infraction with kwargs passed to `post_infraction`."""
        infraction = await utils.post_infraction(ctx, user, "kick", reason, active=False, **kwargs)
        if infraction is None:
            return

        self.mod_log.ignore(Event.member_remove, user.id)

        action = user.kick(reason=reason)
        await self.apply_infraction(ctx, infraction, user, action)

To catch errors, I must put try-except to self.apply_infraction, but this have dependency infraction, what is DB entry, what mean, this can't be after applying infraction.

gusty sonnet
#

Very interesting

#

I'm reading apply_infraction atm

#

And looks like the action is being called way later in the code

#

We may have to edit the scheduler instead

#

Let me take a look at it

gusty sonnet
#

Yep @cold moon the errors are in apply_infraction actually

#

And I found another error

#

The one we're dealing with is py Traceback (most recent call last): File "/bot/bot/cogs/moderation/scheduler.py", line 151, in apply_infraction await action_coro File "/usr/local/lib/python3.8/site-packages/discord/guild.py", line 1655, in ban await self._state.http.ban(user.id, self.id, delete_message_days, reason=reason) File "/usr/local/lib/python3.8/site-packages/discord/http.py", line 225, in request raise HTTPException(r, data) discord.errors.HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body In reason: Must be 512 or fewer in length.

#

The other one is

#
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/discord/ext/commands/core.py", line 83, in wrapped
    ret = await coro(*args, **kwargs)
  File "/bot/bot/cogs/moderation/infractions.py", line 71, in ban
    await self.apply_ban(ctx, user, reason)
  File "/bot/bot/decorators.py", line 203, in inner
    await func(self, ctx, *args, **kwargs)
  File "/bot/bot/cogs/moderation/infractions.py", line 248, in apply_ban
    await self.apply_infraction(ctx, infraction, user, action)
  File "/bot/bot/cogs/moderation/scheduler.py", line 176, in apply_infraction
    await self.mod_log.send_log_message(
  File "/bot/bot/cogs/moderation/modlog.py", line 122, in send_log_message
    log_message = await channel.send(content=content, embed=embed, files=files)
  File "/usr/local/lib/python3.8/site-packages/discord/abc.py", line 856, in send
    data = await state.http.send_message(channel.id, content, tts=tts, embed=embed, nonce=nonce)
  File "/usr/local/lib/python3.8/site-packages/discord/http.py", line 225, in request
    raise HTTPException(r, data)
discord.errors.HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body
In embed.description: Must be 2048 or fewer in length.```
#

Both are from apply_infraction

#

So yeah I suggest looking at that one instead, I'd say do a discussion on how to deal with this - do we want a quick fix to truncate the message, or do we want to refactor apply_infraction which affects other commands as well

sage sparrow
#

Someone changing the #help room names to that of atoms?

patent pivot
#

That's part of the new help system

crude gyro
#

they're not atoms, they're elements

sage sparrow
#

@patent pivot What's changed?

patent pivot
#

We'll be putting out information soon, keep your eyes peeled

sage sparrow
#

Whereabouts?

crude gyro
#

soon

patent pivot
#

Run !subscribe to be notified of new announcements

sage sparrow
#

Sure, will do. Does the main portion of dev for this server occur on the Python-Discord GitHub?

hardy gorge
#

Yes, that's where all of our projects are

#

Discussion also happens in this channel

sage sparrow
#

Need an extra pair of "hands"?

crude gyro
#

we're always looking for contributors, @sage sparrow

#

there are hundreds of open issues

#

feel free to see if you can find something that looks fun

brazen charm
#

Was wondering when going over the org, what is/was the python.org fork for?

sage sparrow
#

Sure, I'll take a look. Looks interesting!

brazen charm
#

Lots of unittest issues open now

crude gyro
#

which failed because that repo wasn't quite up to date with what was actually on the Python.org

sage sparrow
#

Is it up for grabs?

#

Appears to be so.

cold moon
#

No, user is already assigned

sage sparrow
#

Oh right. Didn't notice that.

crude gyro
#

yeah, mike is working on that one.

#

yeah, mike is working on that one.

sage sparrow
#
[test_block]
test_value=1
test_value_two=2
#
[test_block]
test_value=1
test_value_two=2
test_value_three=3
#
[test_block]
test_value=1
test_value_two=2
test_value_three=3
test_value_four=4
#

!aliases

stable mountainBOT
#
Configured aliases

!unwatch => !bigbrother unwatch
!watch => !bigbrother watch
!defoff => !defcon disable
!defon => !defcon enable
!docs => !docs get
!reload => !extensions reload
!get => !get group
!nominate => !nomination add
!unnominate => !nomination end
!nominees => !nominees
!faq => !site faq
!home => !site home
!resources => !site resources
!rules => !site rules
!tools => !site tools
!tags => !tags get

sage sparrow
#

!exception

stable mountainBOT
#

Please provide a full traceback to your exception in order for us to identify your issue.

A full traceback could look like:

Traceback (most recent call last):
    File "tiny", line 3, in
        do_something()
    File "tiny", line 2, in do_something
        a = 6 / 0
ZeroDivisionError: integer division or modulo by zero

The best way to read your traceback is bottom to top.

• Identify the exception raised (e.g. ZeroDivisonError)
• Make note of the line number, and navigate there in your program.
• Try to understand why the error occurred.

To read more about exceptions and errors, please refer to the PyDis Wiki or the official Python tutorial.

sage sparrow
#

!tags

stable mountainBOT
#
**Current tags**

» args-kwargs
» ask
» class
» classmethod
» codeblock
» decorators
» dictcomps
» enumerate
» except
» exit()
» f-strings
» foo
» functions-are-objects
» global
» if-name-main

sage sparrow
#

!reload

brazen charm
#

#bot-commands exists fyi

patent pivot
#

@sage sparrow I don't think it corrects codeblocks in this channel

sage sparrow
#

Which channel would be correct Joe?

#

@brazen charm Sorry for spamming! Missed that channel.

patent pivot
#

it does correct in bot commands

sage sparrow
#

Also, how to test changes to the bot?

#

Would you need to have your own testing server?

patent pivot
#

you would, yes

brazen charm
#

yep, you need that for pretty much any dev

sage sparrow
#

Any dev?

patent pivot
#

you can see the config file to see which channels are required

#

@sage sparrow it can be reproduced in bot-commands, see #bot-commands

brazen charm
#

development

patent pivot
#

it didn't trigger here because we don't have it enabled

sage sparrow
#

I tried it in bot-commands and it seems to work...

#

Ah OK, now I see the difference.

clever wraith
#

should we let channel claimers be able to do !dormant?

cold moon
#

This should good idea

#

@gusty sonnet About this apply_infraction, I think we should look what is wins when we total refactor this. When these are really small or nothing, there is no meaning, but when we get something more than just reason string limit, then we can do it.

patent pivot
#

@clever wraith @cold moon we opted against this, it was discussed during planning

#

the reasoning was that if someone opens a question and it is solved, and then someone else comes along and continues the conversation, the original author can shut down a channel which isn't being used by them but is being used by other people

#

additionally we do not keep a record of who claimed which channels for simplicity

gusty sonnet
#

Yeah that's why I suggested a discussion on the PR @cold moon - we can totally truncate the reason we used for discord.py ban and kick and keep apply_infraction the same - it is working fine and will continue to

#

For simplicity yeah you can simply truncate the reason used for the coroutine ban and kick - textwrap will do a fine job

cold moon
#

I think I currently use this textwrap solution (I add this to modlog embed too), because how much I looked, I can't find any big wins of refactoring. And when there is plan to refactor, then I think this should in different issue/PR pair.

#

But should characters limit in ModLog embed too 512?

gusty sonnet
#

It shouldn't, the paginator should be able to handle that, I'll take a deeper look into ModLog

cold moon
#

I mean, every modlog channel item not use Paginator?

woeful thorn
#

Why would we limit the mod log to 512 characters

woeful thorn
#

The limit is in the error message

#

2048

cold moon
#

I think I have to find good way how to calc how long should entry (I must include other items: member, actor etc. too into limit).

woeful thorn
#

Why? Just slice the string

cold moon
#

Not force slicing. I use textwrap.shorten to avoid breaking word

woeful thorn
#

Ok

#

That still doesn’t require any calculation

cold moon
#

But should Reason like 1900 chars in ModLog (we need to left enough space for other parameters like Actor, User etc.). Then this is not raising this error.

woeful thorn
#

They’re all in the same string

cold moon
#

I know. I mean to avoid reaching limit, I must put limit to reason.

        await self.mod_log.send_log_message(
            icon_url=icon,
            colour=Colours.soft_red,
            title=f"Infraction {log_title}: {infr_type}",
            thumbnail=user.avatar_url_as(static_format="png"),
            text=textwrap.dedent(f"""
                Member: {user.mention} (`{user.id}`)
                Actor: {ctx.message.author}{dm_log_text}
                Reason: {textwrap.shorten(reason, width=1900, placeholder="...")} # Changed this
                {expiry_log_text}
            """),
            content=log_content,
            footer=f"ID {infraction['id']}"
        )
``` What should `width` there?
woeful thorn
#

Why not shorten it in the method that sends the mod log

cold moon
#

OK

cold moon
#

@gusty sonnet I fixed now both errors (action reason + ModLog reason)

cold moon
#

I commented on restricted tags PR

eternal owl
#

oh shit

#

mb

#

what can be a good commit message: cleaner code?

cold moon
#

Maybe (Tags): Removed unnecessary variable creation + joined 2 if statements. This is my commit message style, but maybe something like this?

eternal owl
#

👍

brazen charm
#

that's two changes in one commit

#

should be 2 commits for two different changes

eternal owl
#

those are super minor changes

cold moon
#

I join small commits too

eternal owl
#

just making the code better, no change in functionality

brazen charm
#

they're small and related in no way

native yoke
#

Hey. How could I contribute to the python discord bot?

patent pivot
#

as long as they are unassigned, the issues should describe what we are seeking

native yoke
#

ok Thanks

patent pivot
brazen charm
#

Just testing rn until I confirm the feature is needed but is
the scheduled task #696490796412567614 160898400 and the done task 160898720 differ. after doing cancel_task and schedule_task right after that a cause for concern?

tawdry vapor
#

No it isn't

#

It's to be expected when you do that

brazen charm
#

Thanks, the comment there made it seem mostly ok but wasn't sure

gusty sonnet
valid quest
#

I will need to setup my pc first, I will try to free some time for this

valid quest
#

Its on the contributing page

cold moon
#

Yep, this should

valid quest
cold moon
#

Only staff can, because Contributing is wiki page.

valid quest
#

@gusty sonnet There are a lot of changes, should we just re-write the system in a new branch?

#

I think it will be better

gusty sonnet
#

If it is less of a hassle, sure thing

hardy gorge
#

@valid quest You should be able to edit wiki pages on the website for small mistakes

#

It's obviously a good idea to discuss major changes

valid quest
#

Oh, cool, how can i do that?

#

Just editing the html files, or some other method

hardy gorge
#

You can login to our website using Discord OAuth (in the "More" menu)

#

Once you're logged in and browse to a wiki page, you'll get an edit option

#

You can also make new pages

valid quest
#

Very cool, thank you

#

@gusty sonnet , did you work on that error_handler.try_get_tag util? i think we should add the suggestion after trying to get the tag, as we did before that

#

Another thing, the sending tag function (tags.display_tag in the pr) returned a value representing if a tag was sent or not, based on that we suggest a command

#

I don't see that solution there

#

I need to work on something else now, i will get back to this later, i just need more time to understand the changes

#

If you are free to work on that, go ahead

green oriole
#
[akarys@mojito site]$ pipenv run test  
Loading .env environment variables…
Traceback (most recent call last):
  File "/home/akarys/.local/share/virtualenvs/site-dBpX_aKW/lib/python3.7/site-packages/environ/environ.py", line 273, in get_value
    value = self.ENVIRON[var]
  File "/home/akarys/.pyenv/versions/3.7.6/lib/python3.7/os.py", line 679, in __getitem__
    raise KeyError(key) from None
KeyError: 'DATABASE_URL'```Do I need to do something else to make the tests to work? I already set `DEBUG=1` in the `.env`
crude gyro
#

looks like it expects the DATABASE_URL environment variable

#

usually the docker environment contains this, iirc

green oriole
#

Can I run the tests in the container?

crude gyro
#

yes, but it's not a great idea

#

rather, you should have postgres running in a container and then just make sure this environment variable exists and points at your postgres container

green oriole
#

Okay thanks

cold moon
tawdry vapor
#

No, it shouldn't. That's already the default behaviour and it caused problems because not all operating systems use an appropriate (Unicode) default

cold moon
#

ok

green oriole
#

site_postgres_1 is started, but postgres://pysite:pysite@127.0.0.1:5432/pysite is unreachable

cold moon
#

@green oriole Port should :7777 when you are running in Docker

green oriole
#

Oh yeah, that's a weird config, thanks!

cold moon
#

allow edits from contributors should be Allow edits from maintainers. in SeasonalBot PR template

valid quest
#

I just invoked !close in one of the help channels, seems to have some weird delay, any of you guys encountered this problem? maybe just a one time thing

green oriole
#

How long was the delay?

#

It is probably the bot being rate limited

timid sentinel
#

That's happened to me too but it wasn't for too long, I'd say it probably is just rate limiting, yeah.

valid quest
#

5 seconds iirc, maybe more, and yeah it could be it

valid quest
#

Happened again now, might be a problem with my internet, but with that amount of channel updates, its probably rate limit

hardy gorge
#

We are not being rate limited by Discord, but we may be at the stage at which discord.py is trying to keep us within bounds

#

There are no rejected/ratelimited reponses from Discord's API at this point, though

green oriole
#

I mean, that's the goal of d.py, not run into any actual rate limit, but block the async call

hardy gorge
#

sure

#

but it may not always work and receiving a "hard" rate limit from Discord's end wouldn't be good.

#

We haven't received those since we introduced the system though, so I'd say we're good.

#

If it's just the occasional delay of a few seconds, I'm not too worried yet

green oriole
#

Maybe we shall make the bot send a typing event while it is moving things around

hardy gorge
#

I'm not sure if the solution to hitting rate limits is sending even more API requests

green oriole
#

Rate limits are per events, the general rate limit is way above that

hardy gorge
#

I'm aware of how rate limits work

green oriole
#

Oh well, it isn't that high actually

#

Maybe we should shard the channel managment then

hardy gorge
#

sharding is guild-based, is it not?

timid sentinel
hardy gorge
#

Yes, that was not related to rate limits, but rather a short outage overal

#

Discord returned 500 responses to our bot

#

and to my client as well

molten bough
#

sharding is guild-based, yeah

green oriole
#

Apparently !d list.index said no

#

I feel like this cog could serve some improvements

hardy gorge
#

It's probably because list.index does not exist in the library reference

#

only in the tutorial

#

The only list method that exists in the langauge reference is list.sort

#

that one should work

#

!d get list.sort

stable mountainBOT
#
sort(*, key=None, reverse=False)```
This method sorts the list in place, using only `<` comparisons between items. Exceptions are not suppressed - if any comparison operations fail, the entire sort operation will fail (and the list will likely be left in a partially modified state).

[`sort()`](#list.sort "list.sort") accepts two arguments that can only be passed by keyword ([keyword-only arguments](../glossary.html#keyword-only-parameter)):

*key* specifies a function of one argument that is used to extract a comparison key from each list element (for example, `key=str.lower`). The key corresponding to each item in the list is calculated once and then used for the entire sorting process. The default value of `None` means that list items are sorted directly without calculating a separate key value.

The [`functools.cmp_to_key()`](functools.html#functools.cmp_to_key "functools.cmp_to_key") utility is available to convert a 2.x style *cmp* function to a *key* function.... [read more](https://docs.python.org/3/library/stdtypes.html#list.sort)
brazen charm
#

lists are weird and don't have proper permalinks because they are under data structures

#

I'm planning to work on some improvements but we can't really get those programmatically

green oriole
#

It might be silly, but we could get those through list.sort.__doc__ in an eval

brazen charm
#

the docs are following a different pattern there though so you could try opening an issue

hardy gorge
#

Isn't it just that for lists, the individual methods are listed in the tutorial section of the documentation, while for other data structures, they're listed in the library reference?

#

That sort method is the only list method in the library reference and it works

#

Something like dict.items is also in the library reference, not the tutorial

#

And it works as well

#

list is a bit special in that most of the methods are explained in the tutorial, but not in the library reference

#

e.g., !docs get range will get you the library reference for range, not the entry in the tutorial

brazen charm
#

yeah but they seem to be the only structure which is like that, I don't see anthing linking to that page from the actual reference

#

and the missing permalinks are I guess becaues of where they are but those are the only cases that I'm aware of currently

hardy gorge
#

The other data structures don't have their method explanations in the tutorial

#

Look at dict.items for instance, it will point to the library reference

#

!docs get dict.items

stable mountainBOT
#
items()```
Return a new view of the dictionary’s items (`(key, value)` pairs). See the [documentation of view objects](#dict-views).
hardy gorge
#

That's why it works. List, as far as I can see, is the only common type that has its methods explained in the tutorial, not the library reference

#

The list.sort method is also the only list method that is explained in the library reference

#

and that's why it works, as the only list method

brazen charm
#

it would work if those permalinks were in place (exist in the inventory) but the pattern of how the docs are structured is broken for some reason

#

maybe lists are a datatype they wanmted to show more in detail while someone goes through it?

hardy gorge
#

I think it's because those links don't exist for the tutorial part of the docs

#

I haven't seen a single !docs get point to the tutorials

brazen charm
#

I can find some tut-x symbols in the inventory dump but I don't really know which have the tut and which do not

#

ah it's tut-morelists

hardy gorge
#

ah

#

that works

brazen charm
#

but the methods themselves are missing anything that would be included in the inv

hardy gorge
#

!docs get tut-lists

stable mountainBOT
#

This appears to be a generic page not tied to a specific symbol.

hardy gorge
#

yes

#

It's a bit silly that they are only explained in the tutorial instead of in the actual reference part of the documentation

#

I can see why you'd want to prevent duplicating the docs

#

but, for other common types like dict and set, it just links to the reference

brazen charm
#

they could at least link there from the reference so you can get to the methods from it, I'll make an issue for that when I get the time as I have been going to the wrong page a few times when searching for something with them

cold moon
brazen charm
#

it's a raw descriptor while inside a class

#

you can leave out the staticmethod and it should work, or create a holder class for the decorators

cold moon
#

Okay, I moved this out from class, removed staticmethod and now everything works

cold moon
brazen charm
#

Any staff have an opinion on this? https://github.com/python-discord/bot/pull/868#issuecomment-610482938 Should we just let them wait out when the permissions don't change but the channel goes dormant, send a message to modlog or some other type of handling?

neat sentinel
#

Hello my group is working on one the issues on github and we wanted to know how would you guys go about testing a new command

patent pivot
#

Hey there, which issue are you working on?

neat sentinel
#

the unban issue

#

adding a reasoning ot it

#

to it*

patent pivot
#

so have you got both sides developed? the site & the bot?

neat sentinel
#

I am not sure what you mean by that but what we have done is someone can do the unban command with an reason like "!unban user reason"

#

and it logs into the log where all the commands output goes

#

if theres more to it, then I may not understand all the aspects of the project yet

tawdry vapor
#

Well the reason needs to be stored on our database, but our current schema doesn't support storing separate ban and unban reasons.

neat sentinel
#

I see

#

is there a local database file to work with or is it on a server

tawdry vapor
#

You can read our contributing guide to learn how to set up postgres and our site locally

#

If you're working on this you should have let us know by leaving a comment on the relevant issues.

neat sentinel
#

oh I posted this to my teams group channel. One of the guys work with databases before.

#

okay

#

this is a school project but we plan to do that later.

tawdry vapor
#

This hasn't all been fleshed out yet so there needs to be a discussion on how to go about implementing it

neat sentinel
#

the unban change or changing the database schema?

tawdry vapor
#

Mostly the site/database side of it. I think the bot side is pretty straight forward.

neat sentinel
#

Gotchu, we'll discuss about it later, but thank you for your help Mark

tawdry vapor
#

You're welcome

#

To be clear, this discussion should be with everyone, not internal to your team. So leave comments on the issue or discuss here with us.

neat sentinel
#

Understood

clever wraith
#

is this the right place to talk about the help-channel bot code?

hardy gorge
#

This channel is for discussion our projects, yeah

clever wraith
#

OK

#

So I think I found an issue

#

if a user activates a channel, then deletes their message, as far as i can tell, the bot doesn't ever move the channel to dormant?

# move_idle_channel
 if time_elapsed is None or time_elapsed >= idle_seconds:
# get_last_message
return await channel.history(limit=1).next()  # noqa: B305

If I am right, I think a solution would be to check if the last message was from the bot, and reduce the elapsed time to 5 mins or something

mellow hare
#

The issue with that would be if someone uses a tag command and then the channel sits for a few minutes

#

That'd give a false positive and toss it to dormant

hardy gorge
#

There's always a last message in the channel; either the user message or, if deleted, the bot embed

clever wraith
#

so the history exists even if deleted?

hardy gorge
#

there's history, not the user message itself, but it will get the bot's message before that (with the embed in it)

clever wraith
#

oh, so i'm right, then it's just checking the bot embed

hardy gorge
#

If there is no message, the time_elapsed will be None and we'd still move the channel to dormant

clever wraith
#

that makes it an unused channel effectively

hardy gorge
#

It typically shouldn't occur; having a channel in occupied that has no history in it whatsoever should not happen organically

#

but even if it does, we move the channel to dormant since there's obviously nothing going on in the channel

clever wraith
#

the available message occurs when the channel moves to the available queue

#

now imagine it's there for 2 hrs

#

and someone activates it

#

then deletes their message

cold moon
mellow hare
#

Right, but he's saying that there is still always going to be a message in there from the previous session or from the bot

hardy gorge
#

@clever wraith Yes, that means the channel would be moved as soon as the check occurs

mellow hare
#

So there is still a last message to check

hardy gorge
#

The check occurs after the initial delay, which is 30 minutes

#

So, the channel would sit there unused for 30 minutes (or until a helper+ closes it)

clever wraith
#

understood

tough imp
#

@cold moon I think it's ok, but what would it look like in a codeblock?

clever wraith
cold moon
#

@clever wraith when i put anything between them, emojis will be really small

#

Like

#

1️⃣

#

1️⃣ |

gusty sonnet
#

You can put a \ in front of it as well, it'll revert to the unicode emoji

cold moon
#

Okay

gusty sonnet
#

like 🔥 and \🔥

tough imp
#

i don't mind the small ones

eternal owl
tawdry vapor
#

Sure, I'll get on it

eternal owl
#

thanks!

valid quest
glass pecan
#

yeppers

#

already submitted my verification

valid quest
#

nice! which bot?

glass pecan
#

just some eve online botto

#

nothing fancy

valid quest
#

Oh i think i know him, nice

#

How many users?

glass pecan
#

Firetail it's called. It's in the middle of a rewrite as I inherited a fair amount of code debt after taking the project over.

#

Um

#

lemme check

valid quest
#

but anyways i was talking about @stable mountain bot, we can make the ui better with these changes, and much more

hardy gorge
#

This is not relevant for our projects here, right? Since we're not even close the underlimit of 75 guilds with any of our bots.

glass pecan
#

And correct ves

valid quest
#

@hardy gorge Yeah, but i was talking about the massive ui/ux changes that discord brings

glass pecan
#

the ui/ux changes is nice but far off yet

#

gotta get intents sorted first

valid quest
#

Nice! mine has around the same amount and i didn't submit yet, big oof

glass pecan
#

those changes though will be closer to extensions, it seems

valid quest
#

Mhm

#

alright then

glass pecan
#

and instead of using msg prefixes, it'll use the backslash commands

#

which feels pree weird

#

at least it means auto-complete will be a thing for bot commands

cold moon
#

I think there will be something like clicking to message and bot can do actions with it and something like these changes.

glass pecan
#

i'm most keen for the interaction ui changes with actual ui elements

#

and the context actions

#

those two together are sweet

valid quest
#

i agree

hardy gorge
#

How I see it is that we've seen a sneak preview of things they're working on, but I don't have a clue what it will actually mean for us and @stable mountain

#

That means there's not much to plan yet

valid quest
#

yeah

brazen charm
hardy gorge
#

Good question. That commit is already a bit up in the commit history, isn't it?

#

I'm not awfully attached to the git blame history of that particular constant though

cold moon
#

YES! Finally initial TicTacToe work. Now I have to make system that check for winning

cold moon
#

I have problem: textwrap.shorten is removing newlines from string. How to make this that this don't remove newlines?

gusty sonnet
#

It has a keyword @cold moon

#
replace_whitespace=False```iirc
brazen charm
#

@hardy gorge Will you push it in or should I do it normally with copying the initial commit message?

#

The inclusion of emojis into channel names also breaks logging on windows because of encoding again, should I throw in a fix with the open PR?

cold moon
#

ok, thanks

frozen galleon
#

Hi I'm creating my own bot project and I'd like to use some files from your Python Bot's github repository, so I was wondering if this copyright notice in my LICENCE.md is sufficient for that, since it is licenced under MIT, or if I should also mention it in some other places, or somehow adjust the licence:

https://github.com/koumakpet/CommandBot/blob/master/LICENSE.md

hardy gorge
#

Our bot has an MIT license, so I see no issue with it

#

Good luck with your bot by the way

frozen galleon
#

okay, thank you than 🙂

cold moon
#

FINALLY! Human vs human Tic Tac Toe is ready. Now is only AI

#

@gusty sonnet This is not working. This still remove newlines

gusty sonnet
#

Ah I see, I'm reading the docs for it

#

replace_whitespace has no effect for shorten

#

Hmm, you may need to wrap manually

#

By default shorten will collapse all whitespace, including newlines

cold moon
#

Huh, this will be hard

gusty sonnet
#

It will take a bit of effort, like this

#

!e ```py
import textwrap

string = '\n'.join(map(str, range(1000)))

shortened = textwrap.wrap(
string, width=10, placeholder='...',
replace_whitespace=False, break_long_words=False,
max_lines=1
)[0]
print(shortened)

stable mountainBOT
#

@gusty sonnet :white_check_mark: Your eval job has completed with return code 0.

001 | 0
002 | 1
003 | 2
004 | 3...
gusty sonnet
#

idk if creating a TextWrapper will make this less of a hassle

#

You can also wrap manually via slicing lol

cold moon
#

I have to do this in only one place: ModLog.send_log_message

cold moon
#

Should tic-tac-toe AI easily beatable or should this almost/totally unbeatable?

green oriole
#

I’d say in the middle?

#

or configurable

cold moon
#

Then middle. Because I have to select which logic to use (every logic have it's own level) so configurable will mean more code for every level.

green oriole
#

I mean, it could be a fun thing to implement all of them

#

I can help you if you want, it sounds like a fun thing to do

cold moon
clever wraith
#

not to sound picky

#

error handler for @dusky shore have this spelling mistake

clever wraith
#

its, not it's

tawdry vapor
#

AG, you're welcome to fix any spelling mistakes you find.

#

It's not being picky, at least not in this case. It's pretty clearly incorrect.

crimson tinsel
#

So I am trying to be more involved here, and I am looking at the issues for the bot and I am trying to understand some of the issues better so I can join the planning process. For !ping command #697 what is it actually asking to do?

tawdry vapor
#

I thought the issue explains it pretty clearly

crimson tinsel
#

for the bot latency, does it mean on startup or when the command is sent?

#

sorry still new to the discord bot realm

tawdry vapor
#

The time between when the message was sent (users need to send a message to invoke a command) and when the bot detects the message as a command.

crimson tinsel
#

is there a way to get the timestamp of when a message was sent?

tawdry vapor
#

Yes, but I don't remember the exact name of the attribute

#

create_at or something

#

it's documented.

crimson tinsel
#

ahhh okay, still learning lol thanks 🙂

patent pivot
#

!int e ctx.message.created_at

stable mountainBOT
#
In [17]: ctx.message.created_at
Out[17]: 
datetime.datetime(2020, 4, 11, 23, 16, 21, 549000)```
eternal owl
#

@tawdry vapor I have gone for this approach

parent_folder = file.parent
if not str(parent_folder).endswith("tags"):
    tag_index = str(parent_folder).index("tags")
    sub_folder = str(parent_folder)[tag_index+5:] # +5 because len("tags/") = 5
    tag["restricted_to"] = sub_folder```
this should be cross platform hopefully.(I cannot test it on windows.)
Here `file` is pathlib.Path object
tawdry vapor
#

Why use string manipulation?

#

I find it less hacky to stick to pathlib's .parent and .parents

eternal owl
#

for .parent and .parents, will it be forword slash / even for windows device?

tawdry vapor
#

I don't get your question but if you are using solely pathlib then you need not concern yourself with slashes.

brazen charm
#

Or outside of it too because windows can handle them, but pathlib has no concern with slashes and mostly out of string methods

eternal owl
#

okay

tawdry vapor
#

It could be as simple as list(file.parents)[-4].stem to get the restricted_to value. I don't know if -4 is the correct index but you get the idea.

#

I think you'd need to still check that it's a directory rather than a file

#

Well, name is more appropriate than stem

eternal owl
#

okay, will look into that

#

thanks!

neat sentinel
#

quick question, how does the bot find where all the commands are once its called? like in the help command

brazen charm
#

Do you mean the cogs with "where they are"?

neat sentinel
#

yea

#

like which file is it from

#

alot of them are the same name as the command but some aren't

brazen charm
exotic ember
#

does the bot delete the message manually marking a channel dormant?

crude gyro
#

yes

#

that was implemented recently

#

and is still being evaluated

exotic ember
#

if someone mentions that their help channel was marked dormant before they were done with it, it would be good to know if it was because someone manually made it dormant, or an error with the activity checker

crude gyro
#

hmm, valid point

exotic ember
#

I had to go look at the config to see the inactivity limit, which should be 30 minutes?

#

and is there / should there be an !undormant command?

crude gyro
#

30 minutes, yeah

#

we don't really want users executing an !undormant at least, we want channels to expire - but to make something like that available to staff only? I don't know, maybe.

exotic ember
#

I was thinking a command for Helper+, incase someone mistakenly dormants a channel only to realize there's still activity going on

#

also thoughts on a custom dormant message based on whether it was marked manually or automatically? I can create issues for both

crude gyro
#

<@&587606783669829632> how do you guys feel about these two ideas cuneiform_this

tranquil topaz
#

like an !undo command?

#

i like the idea

exotic ember
#

yep, but specifically to undo a channel made dormant

#

unrelated to the !undo issue in bot right now

crude gyro
#

there's an undo issue? I thought that idea was met with a bunch of resistance

exotic ember
#

it's still up, not much discussion there

tranquil topaz
#

yes, but i did not mean to comment on that issue

exotic ember
#

I personally do not like the idea of that, so I'll put in a few words

tranquil topaz
#

my !undo comment was very much in the general way

crude gyro
#

yeah no this is specifically for undoing !dormant invocations though, @tranquil topaz

#

but yes

tranquil topaz
#

!undoclose and !undodormant is fine if you want 😄

#

i hate writing dormant.. i always have to think to write it correctly 😄

crude gyro
#

!undormant and !open, maybe

tranquil topaz
#

!awake !open

crude gyro
#

I'm fine with both suggestions, @exotic ember

#

just, for the record.

exotic ember
#

coolio

crude gyro
#

I'm sure some of the other core devs will chime in with an opinion later

#

but you can just open the issues

#

and post them here

exotic ember
#

will do

#

Issues are in!

hardy gorge
#

I think that the latter should be solved by reversing the change that introduced the deletion of the message containing the command

#

It's now obvious that it leads to confusion and having the message there with the command invocation is far more obvious than changing a line in an embed

#

In this case, the user who opened the channel closed it themselves

#

If we just leave the command invocation out in the open, there's no confusion

exotic ember
#

good idea

clever wraith
#

I think that the latter should be solved by reversing the change that introduced the deletion of the message containing the command
@hardy gorge you could also have a bot message with "This channel was closed by <Name>" if you don't want command spam, as a suggestion

cold moon
#

This should in dormant message

mellow hare
#

What would be the one for a timeout?

eternal owl
clever wraith
#

@mellow hare maybe:
This channel has been marked as dormant: closed by user <Name>.
This channel has been marked as dormant: timeout due to inactivity.

#

It doesn't have to be overly complicated

mellow hare
#

True enough

cold moon
#

About these moderation tests, how should I test apply_ban? This have role position check decorator, what raise error: TypeError: '>=' not supported between instances of 'MockRole' and 'MockRole'

hollow cedar
#

I like the idea of !open, it would go well with the existing dormant alias !close and would be easy to remember. I think the need might be a bit niche, but in cases where a channel was mistakenly closed it would be quite useful.

green oriole
#

@cold moon you should just write the appropriate dunder of the MockRole class

mellow hare
#

So is the reasoning for !open to reopen a dormant channel to keep the context?

green oriole
#

I think yeah

cold moon
#

@green oriole i already found easier solution: I use ints instead role mock

green oriole
#

I don't think that's a good solution

#

The function is meant to get roles as an argument, not ints

#

If in the future we change the function to use dome role attribute, like the color for whatever reason, the test will break even if the code still function properly

cold moon
#

How to extract args/kwargs from coroutine?

hardy gorge
#

What do you mean by extract? Can you give an example of what you mean?

cold moon
#

I'm writing tests for reason shortening:

action = ctx.guild.ban(user, reason=truncated_reason, delete_message_days=0)
await self.apply_infraction(ctx, infraction, user, action)

and now in tests:

has_active_mock.return_value = False
post_infraction_mock.return_value = {'foo': 'bar'}
self.cog.apply_infraction = AsyncMock()
self.bot.get_cog.return_value = AsyncMock()
await self.cog.apply_ban(self.ctx, self.target, "foo bar" * 3000)
ban = self.cog.apply_infraction.call_args[0][3]

I have to get access to action's reason.

tawdry vapor
#

Maybe ban_coro.cr_frame.f_locals but man is that hacky. I'm not familiar with internals too much so IDK if there could be more in that dict besides the argument values but I suspect yes, though doesn't seem like it'd matter.

#

Also inspect.getargvalues(ban_coro.cr_frame) works but I don't really see the benefits of using inspect over attribute access. I also didn't see a way to get the frame for a coroutine with inspect.

#

That being said, is there not a way to just check it while asserting the await?

cold moon
#

This will be awaited in self.cog.apply_infraction, but this is AsyncMock in this case.

tawdry vapor
#

Hmm right

#

Well this all wasn't written very well by me

#

It was just meant to clean up the really mess code that came before it

#

Wasn't designed with testability in mind so i think that will work against you a lot here

#

The plan was to give moderation a proper rewrite, probably some OOP based system for infractions.

#

But nothing came of that

#

So uh, just beware all ye who enter

cold moon
#

I currently do this with cr_frame.f_locals. This is currently easiest way and when system get rewrited, this can be changed.

gusty sonnet
#

I mean, you can open an issue on that Mark

#

So we can start with what everyone thinks about it, and who wants to take it

tawdry vapor
#

Well what I am trying to say is I don't think it's the best idea to tackle writing tests (a significant effort in this case) for something that is not very testable and will hopefully, eventually, be replaced. But you can proceed if you wish. Just know what you're getting yourself into.

#

Yeah I will get around to opening an issue. I just haven't since I was waiting for some more concrete plans/design ideas.

cold moon
#

I'm writing tests only for reasons shortening currently, not for full cog

dry topaz
#

Can somebody explain me how the timed mute works on @stable mountain?

#

I've been in it for a day, I can't find ANYTHING out

glass pecan
#

mute infraction is put in a db and the muted role given to the user

#

then a task is started that removes the role when it's datetime of expiry is reached

dry topaz
#

Which db do y'all use?

glass pecan
#

the bot on starting retrieves any active mutes from the database, and reschedules the task to remove them at the right datetime again, so it's persistent

#

we use postgresql

dry topaz
#

Where do you host it?

glass pecan
#

on our server?

dry topaz
#

I need to get a bit more into db

#

Your server?

#

How is it made?

glass pecan
#

i don't understand the question. a server is just a computer that can access the internet and host web services

#

we use Linode as our server host

dry topaz
#

What plan?

#

Like, how much does it cost?

#

I have a budget of $15 a month 😛

glass pecan
#

there's multiple different options for VPS plans. You're better off going to the host site and checking what's available from them and what might be suitable for your own usage.

#

otherwise any off-topic for super general questions will do and plenty will likely be able to pitch in

dry topaz
#

Can a db be hosted somewhere for free?

#

Or is it not allowed to ask for that stuff in here?

glass pecan
#

it's not really on topic for here, no

cold moon
green oriole
#

You forgot to await a coroutine

#

See the first line

cold moon
#

Yeah. I don't really need to await it for this test, but I added awaiting to end to avoid warning

neat sentinel
#

hello, I was wondering. What database driver it uses to access postgres in the program during runtime?

hardy gorge
#

Our bot? It does not connect to the database directly but rather communicates with a REST API on our website.

#

The database connection there is managed by Django's built-in ORM and database functionality

neat sentinel
#

oh I see thank you

#

it wouldn't be possible to make any local database changes for development purposes? all the changes need to be done through those who manage the API?

cold moon
#

What you try to do? This may be possible to be done without direct DB editing.

neat sentinel
#

I wanted to cache API request so I wouldn't run into issues where I run out of requests

cold moon
#

Out of requests?

neat sentinel
#

I can do this locally, but I thought because there was already a database it can be done there

#

yea for github API to get link to github repo and modules

#

how come when we use the docker it the container is called postgres when maria db is used? how does postgres interact here

cold moon
#

What? I don't understand this anymore

hardy gorge
#

I'm not sure either

#

We're using a Postgresql database

#

Can you clarify what you're talking about, @neat sentinel?

#

I think there's some kind of misunderstanding

neat sentinel
#

sorry I read that wrong I thought maria db was associated with django for an moment

#

but I understand now thanks

eternal owl
crude gyro
#

<@&295488872404484098> <@&587606783669829632>

I've done a major clean-up of the branding repo, scrubbing the history for huge files and force pushing the history rewrite to master, as well as getting rid of old branches. This has reduced the repo size to about 50MiB, down from nearly 300MiB.

However, because of the history rewrite, everyone who has this repo cloned should just delete their clone and clone a fresh one.

Going forward, let's try to keep this repo only to asset files that are directly useful to us, and related to this community. So, no memes, no project files (like PSDs), no compressed archives, nothing like that. Just PNGs, GIFs, SVGs, MP3s, and so on.

#

oh actually, some of the <@&267630620367257601> may have this cloned without having the Contributor role. You guys should see this too. cuneiform_this

ornate moat
#

Do you have git LFS

crude gyro
#

no, and I don't think we really need it for what this repo should be used for.

hardy gorge
#

I'd still add SVGs to the list of files we want

crude gyro
#

oh yeah

#

of course

hardy gorge
#

Some people may consider those akin to PSD project files, as they're usually the source for the actual prod png files

crude gyro
#

yes.

#

you can import an svg right into your vector software and it more or less works as a project file

#

not quite as nice but at a fraction of the size.

green oriole
#

I think we should still have psd files if we want to modify them later on

ornate moat
#

LFS just stores text pointers to the files and then you can fetch them from the LFS storage unit

#

if deemed necessary

crude gyro
#

yeah, I'm aware. we just haven't really deemed it necessary yet

#

the only thing we were really using PSDs for were my silly backgrounds

green oriole
#

PyDis cloud isn't public though

crude gyro
#

and of course, I haven't deleted these PSDs and don't intend to, but I don't think they need to be in branding

#

no, pydis cloud isn't public. nor will it ever be.

green oriole
#

My point wasn't about making it public, it was about making source psd files open to the world

#

You are just restricting contributions even more like this

crude gyro
#

Yep. There are still SVGs, I don't really see the problem.

#

what exactly do you think we need PSDs for?

green oriole
#

Ah that's fair then

crude gyro
#

the difference is that a PSD can be over 100MB while an svg is hardly even 10kB

#

and we're working with vector on 90% of the stuff we make

#

(it would be 100% if not for me)

#

besides, even with LFS we still have store them somewhere

#

but if we see the need for large files we'll revist the LFS idea in the future, I'm sure.

green oriole
#

I don't understand, GitHub can host LFS files

#

Why would you store them on the pydis cloud then?

crude gyro
#

I'm not saying we would, it came up earlier.

#

anyway we don't need LFS if we're not gonna put big files in it, and right now the plan is to not put big files in it so why are we talking about LFS. We'll revisit it if we need large files.

#

the way I understand LFS (and that understanding is very limited), people have to set it up locally

#

so it's almost like a pre-commit hook, then, and ensuring that that actually gets done is another problem to solve.

#

but maybe there's some mechanism to make it impossible to push a large file? I don't know.

patent pivot
#

I don't think we could use LFS

#

I recall there being like an 8GB file, LFS maxes out at 2GB and also has a 1GB limit without a data package iirc

exotic ember
cold moon
#

What is this?

exotic ember
#

source command embed

tawdry vapor
#

What the difference between linking to the cog and the module?

#

I don't think the cog is too relevant especially given that, in practice, the modules have similar names to the cogs and they contain one cog at most

#

Also what is the code block supposed to contain? Command name?

stable mountainBOT
#

:incoming_envelope: :ok_hand: applied mute to @tidal stream until 2020-04-18 05:54 (9 minutes and 59 seconds) (reason: duplicates rule: sent 4 duplicated messages in 10s).

sullen phoenix
#

!ban 695178390394634242 joined just to spam and troll

stable mountainBOT
#

:incoming_envelope: :ok_hand: applied ban to @tidal stream permanently.

exotic ember
#

@tawdry vapor
The cog links to the line where the Cog is defined, ie. class Snekbox(Cog): on line 48

The module shows the path to the file where the command is defined, with each segment linked to the respective url in the repo, so the bot directory, the cogs directory, then the snekbox.py file

the code block has the full command name, so !source t g will return !tags get in the code block

tawdry vapor
#

Thanks for the explanation

#

I still don't think the cog link is particularly useful but it doesn't take up space really so it can stay as far as I am concerned

crude gyro
#

I agree with Mark that the cog is rarely useful.

#

but it helps flesh out the response a bit. would look a bit short without it

#

and if we did have a single file with many cogs (don't we do that for moderation?) then it would be useful.

hardy gorge
#

I don't think we have many files with multiple cogs in them

#

I don't think the infraction subpackage does that either

#

That said, I like the module path breakdown and I don't mind a cog link.

#

However, couldn't we link to the command there instead?

#

I don't really like linked titles of embeds. They don't look great and I don't think it makes for a great UX/UI either

crude gyro
#

oh yeah, that sounds like a better option

cold moon
#

About this PEP issue I have question: Why we don't use int type hint to automatically convert + check it?

glass pecan
#

@cold moon what issue?

cold moon
#

891

glass pecan
#

of what repo?

cold moon
#

bot have !pep command

glass pecan
cold moon
#

Yep. So maybe is better use type hinting instead isdigit

glass pecan
#

if we don't accept multiple arguments, then it should be using a converter, yep

eternal owl
green oriole
#

Contributors doesn't get write access anymore do we?

eternal owl
#

nop

#

I just got that email too

patent pivot
#

@eternal owl regarding implementation, I spoke to akarys about this a bit ago

eternal owl
#

okay, I will look it up, thanks!

patent pivot
#

I'm pretty sure there was already an issue open...

#

give me a momment

eternal owl
#

ty

green oriole
#

How am I supposed to finish my PRs if I don't have write access anymore >_>

patent pivot
#

you can clone the branch on pydis repo to your own fork

#

it isn't a huge git operation

brazen charm
#

@patent pivot Think 169 can also be closed with the new issue

#

.issue 169 bot

#

can we allow that here?

patent pivot
#

yeah, I'm okay with that here, feel free to 1 line PR it whenever and I'll get it through fast

#

also you are right, 169 can be closed with the new issue

#

@cold moon I'm going to write up implementation details, then we'll do claims

cold moon
#

okay

patent pivot
#

@cold moon done

brazen charm
#

Made the PR joe

#

.issue 400

patent pivot
#

will take a few to deploy

brazen charm
#

oh right

#

Also found my environment was broken when lint failed so that's a plus

patent pivot
#

.issue 890 bot

dusky shoreBOT
patent pivot
#

all done

brazen charm
#

.issue 400

brazen charm
#

you override it with your perms 😛

patent pivot
#

true

cold moon
#

OK, can I get assigned now? I think this is not super hard to do. But one question: What should cog name? News? PythonNews?

patent pivot
#

@cold moon News is sufficient, I'm assigning you now

#

If you need anything let me know, when you have a working prototype ping us and we'll make a channel

cold moon
#

ok

eternal owl
#

https://github.com/python-discord/site/issues/189
I'd love to work on this and the corresponding issue in the bot repo.
I am not sure about the implementation yet, but this is what I got in mind rn:

URL ENDPOINTS(API):
/raffle/<name_of_raffle>/add - to participate the raffle
/raffle/name_of_raffle/remove - opt out of the raffle
/raffle/name_of_raffle/roll - get results

RAFFLE MODEL:
Name - The event name.
Description - a breif note on the event.
user(ManyToMany field) - all users participating
end_date_time(Can be None) - the date and time the raffle will end.
number_of_winners(default=1)

BOT SIDE COMMANDS:
.raffle <name_of_raffle> add - join the raffle
.raffle <name_of_raffle> remove - opt out of the raffle
.raffle <name_of_raffle> roll - get result(gives a warning if there is a timer set)
#

What do you guys think?

cold moon
#

About these news, how should this check is this new already posted?

green oriole
#

Go through the message history in the channel

patent pivot
#

That's one way of doing it

#

alternatively you could use the key value storage on the bot

cold moon
#

I think I'll use message history. I don't really like JSON files 😅

woeful thorn
#

Message history is going to get real annoying after the channel is around for a while

patent pivot
#

it isn't a JSON file

green oriole
#

We don't have permanent storage on the bot do we?

patent pivot
#

we have an API endpoint for key value storage on the bot

green oriole
#

do we?

#

It must be recent then

woeful thorn
#

The bot's permanent storage is our site

green oriole
#

Yeah, last time I asked about this one you said it should be used only for settings

#

This shouldn't change at runtime in most cases

#

You need to add the entry to the validator anyway, you'll need 2 PRs

patent pivot
#

that is one line though

cold moon
#

Maybe storage last_news_check to site and this post news that is created after this datetime

red fox
#

Hey!

patent pivot
#

better name would be last_news_post if we are going off IDs, last_news_created_time if time maybe?

#

since last_news_check indicates it is the last time we polled

#

plus we'll also need another key for RSS

#

though you could store that in the dictionary in the same key

#

@red fox Hello!

red fox
#

How are you?

green oriole
#

But that's clearly not a setting

cold moon
#

This should storage date too for case when bot is down. Just secure.

green oriole
#

It doesn't make any sense

#

We would be better creating an actual key pair storage for the bot

patent pivot
#

this is actual key val

#

if you don't like the name you can change it

#

They have different purposes

#

🤨

red fox
#

Yeah I realized it...

cold moon
#

I start making this tomorrow. Gonna go sleep now

patent pivot
#

👌

eternal owl
red fox
#

Is it possible that we can make our own bot?

patent pivot
#

@red fox It is, Discord.py is the library you would be looking for

red fox
#

Because like all the cogs and stuff is a bit above my brain

patent pivot
#

@eternal owl proposal looks good to me

red fox
#

@red fox It is, Discord.py is the library you would be looking for
@patent pivot I use that only

patent pivot
eternal owl
#

okay, can you assign me to the site one 🙂

patent pivot
#

@eternal owl how do you plan on identifying raffles

eternal owl
#

title/event name?

patent pivot
#

I'm not a fan of the bot commands

#

I have a small change, one sec

eternal owl
#

won't there be an announcement during a raffle?

woeful thorn
#

Do we really need more than one raffle at a time?

patent pivot
#
.raffle join <name_of_raffle> - join the raffle
.raffle leave <name_of_raffle> - opt out of the raffle
.raffle roll <name_of_raffle> - get result(gives a warning if there is a timer set)
#

that's another thing yeah

#

in fact

#

I'm skeptical we need site storage?

#

is there a reason we can't do reactions?

eternal owl
#

we can

#

that will be work only on the bot side then

woeful thorn
#

And lose all the entries if the bot restarts?

patent pivot
#

and then eliminate the need for any .raffle join or .raffle leave and then just implement a .roll <message id> to pick a random reactor?

#

we can always fetch reactions

woeful thorn
#

How do you know where to fetch reactions from?

patent pivot
#

we pass in the message ID when we roll

eternal owl
#

using message link

patent pivot
#

!int e ```py
msg = await channel.fetch_message(701484548952817677)
print(msg.reactions)

stable mountainBOT
#
In [1]: msg = await channel.fetch_message(701484548952817677)
   ...: print(msg.reactions)
   ...: 
[<Reaction emoji='🇦' me=False count=1>, <Reaction emoji='🇧' me=False count=1>, <Reaction emoji='🇨' me=False count=1>, <Reaction emoji='🇩' me=False count=1>]

eternal owl
patent pivot
#

!int e ```py
import random

msg = await channel.fetch_message(701484548952817677)
reactors = set()

for reaction in msg.reactions:
async for user in reaction.users():
reactors.add(user.id)

print(random.choice(list(reactors)))

stable mountainBOT
#
In [3]: import random
   ...: msg = await channel.fetch_message(701484548952817677)
   ...: reactors = set()
   ...: for reaction in msg.reactions:
   ...:     async for user in reaction.users():
   ...:         reactors.add(user.id)
   ...: print(random.choice(list(reactors)))
   ...: 
263560579770220554

eternal owl
#

yep, thats my id

patent pivot
#

sad face

#

but I think I prefer that proposal?

eternal owl
#

which?

patent pivot
#

reactions & pick from that

#

@woeful thorn what do you think of that solution?

eternal owl
#

yea me2

woeful thorn
#

I don't really care either way

patent pivot
#

@crude gyro @hardy gorge do you guys have an opinion on raffles? Should we do entry through a command and have site storage or use Discord & fetch reactions?

eternal owl
#

If I'm not wrong, we had a jetbrains license giveaway and we used reactions

hardy gorge
#

Wouldn't site complicate this by a lot? And what would it store?

#

It's basically a very temporary cache

#

We'd still need to get the reactions to do the raffle, right? Or do you want to have them to react on the website?

patent pivot
woeful thorn
#

We agreed on site a year ago when it was suggested

hardy gorge
#

Oh, okay

woeful thorn
#

No reason we can't change our minds

eternal owl
#

why did we agree on site 🤔 (just curious about the reasons)

woeful thorn
#

I don't know, it was a year ago

hardy gorge
#

If I have to take a guess, it's because of what was mentioned above: Remembering the message with the reactions.

#

We'd still have to fetch reactions after a bot restart to count the reactions given between bot shutdown and it coming back up

woeful thorn
#

It's more likely we wanted to do a spinner on the site or something

hardy gorge
#

could also be, yeah

eternal owl
#

or

#

we don't have to store anything, just do the math when rolling

crude gyro
#

could do seasonalbot and use the persistance there - or wait until we have regular bot persistance

eternal owl
#

fetch reaction/users while rolling

crude gyro
#

yeah the spinner on the site was an idea we had at one point - joseph even wrote some code for that for one of the code jams

eternal owl
#

code jam 5

#

the micro controller giveaway

crude gyro
#

but I don't really feel an urgent need for that anymore

woeful thorn
#

We don't need persistence if we're not going to do anything fun with it

patent pivot
#

The code for discord is ludicrously simple

#

!int e ```py
import random

msg = await (guild.get_channel(354619224620138496)).fetch_message(699734335951208589)
reactors = set()

for reaction in msg.reactions:
async for user in reaction.users():
reactors.add(str(user))

print(random.choice(list(reactors)))

stable mountainBOT
#
In [6]: import random
   ...: msg = await (guild.get_channel(354619224620138496)).fetch_message(699734335951208589)
   ...: reactors = set()
   ...: for reaction in msg.reactions:
   ...:     async for user in reaction.users():
   ...:         reactors.add(str(user))
   ...: print(random.choice(list(reactors)))
   ...: 
Gugi9000#1408

patent pivot
#

from the aeros announcement

crude gyro
#

can someone give me the tldr for why we need persistance at all?

#

what fun features are we talking about

woeful thorn
#

Spinner

crude gyro
#

okay.

woeful thorn
#

Also, again, this was over a year ago

crude gyro
#

well, I guess it could make sense as part of the code jam management toolset, but

#

naw, I don't feel an urgent need for this at all.

#

I'd rather just have the bot code

#

and use emojis

#

it works fine

patent pivot
#

we could still do fun stuff with it should we want to, we can always extract a list of people who reacted and make something fun with it

#

but it isn't urgent

eternal owl
#

a few changes to the reaction method:

.raffle [message_id] [time]

here:
- message_id : ID of the message to which members will react to(to join the raffle).
- time : time when the raffle will end and the results will be posted by the bot automaticall
#

and a roll command

#

if no time is set

woeful thorn
#

What are we going to do with time without persistence?

eternal owl
#

nvm, no need time then

crude gyro
#

not sure what this will even do

#

wouldn't a roll command be all we need?

eternal owl
#

okay

#

the roll command will just take in the message_id as input

crude gyro
#

how will it know what emoji to use?

woeful thorn
#

It shouldn't matter if you just use a set of the reactors

crude gyro
#

like what

eternal owl
#

wait

#

we need more config

#

like number of winners n stuff

#

because in code jam5 we had multiple rolls

crude gyro
#

sure. so .raffle [message_id] [number_of_winners]? and then we just use a set of any reactors?

#

I guess that works

patent pivot
#

just add an argument for number of reactors and pass it into random.choices

eternal owl
#

yea, the k param

crude gyro
#

but number of winners should be optional

#

and default to 1

eternal owl
#

okay

patent pivot
molten bough
#

Good lord.

eternal owl
#

flashy

woeful thorn
eternal owl
#

those firewords kinda remind me of coconut trees

dry topaz
#

Will I become a contributor if I add some cool features to @stable mountain?

#

Or some stuff to the website?

brazen charm
#

if you make significant contributions

dry topaz
#

So if I make new stuff for a week and make it noticeable for the devs, will I get the role/become a contributor?

brazen charm
#

the stuff has to be approved and be code with some degree of quality

dry topaz
#

O_o

brazen charm
#

I can't speak for the role as I'm not staff, but you can't create PRs out of the blue

dry topaz
#

PRs?

brazen charm
#

push requests

dry topaz
#

Oh yea

#

But I can't run the bot to test some stuff

#

I did make a pull

#

Even if I replace the toke with something else, I can't run the bot

#

Hold on, I'll give you what error I get

brazen charm
#

Which one are we talking about now?

dry topaz
#

@stable mountain

brazen charm
#

it requires more extensive setup

#

along with having the site running

dry topaz
#

What site?

brazen charm
dry topaz
#

Oh

#

Thanks for the link

brazen charm
#

I'd recommend starting with seasonalbot

dry topaz
#

Why is that?

brazen charm
#

Simpler to setup and the bot is mostly simpler in general

#

with its features etc.

dry topaz
#

I don't have this requirement 😦

brazen charm
#

you can set it up locally

#

through the linked guide

dry topaz
#

Oh

#

Hope it is easy 😕

brazen charm
#

depends on how successful you are with getting docker up if you're going through that

dry topaz
#

Umh

#

No

#

Is there a way to learn docker?

#

It is getting quite a popular thing

#

I don't like interacting with things that I don't know how it works

#

Often, it's scary

#

Ow

#

There's many complex things in the requirement

#

I'll go with @dusky shore

tawdry vapor
#

Well in theory it's not complex if you just use Docker

#

But alas Docker has problems on Windows

dry topaz
#

Why?

#

Why on windows?

tawdry vapor
#

Cause it needs hyper-v, which is not available on the home edition

#

That's the main thing

#

But there have been other quirks which I do not remember

dry topaz
#

Huh.

#

What about on linux?

tawdry vapor
#

Works great on linux

dry topaz
#

I'm planning on setting up a linux os as the dual boot

#

I would do it now but I can't get a usb because of the lockdown..

brazen charm
#

I'm on win with docker and it wasn't terribly nice to set up but after it's working it just works (only using it for site/db)

dry topaz
#

What else can you use it on?

brazen charm
#

the bot can also run in a container if you meant that

#

but I'm running it directly through pipenv

cold moon
#

How to make bot creating new item to bot/bot-settings endpoint?

#

Oh! I have to change site too.

#

But how I can make that bot automatically create news setting?