Compare commits

...

3 commits

Author SHA1 Message Date
tobi c2029df9bc
[feature] Allow emoji shortcode to be 1-character length (#3556)
* [feature] Allow emoji shortcode to be 1-character length

* testerino fixeroni

* spaghet
2024-11-21 12:13:55 +01:00
dependabot[bot] daf55ba6a5
[chore] Bump cross-spawn from 7.0.3 to 7.0.6 in /web/source (#3552)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-21 11:06:41 +01:00
Jannis 9ace025da1
[bugfix] post counters should not include direct messages (#3554)
* [bugfix] post counters should not include direct messages #3504

The fix is relativly simple, it just adds a line to the relevant
function which excludes all private posts.

* Formating fix

* mb
2024-11-21 11:06:06 +01:00
14 changed files with 31 additions and 24 deletions

View file

@ -4920,7 +4920,7 @@ paths:
- description: The code to use for the emoji, which will be used by instance denizens to select it. This must be unique on the instance. - description: The code to use for the emoji, which will be used by instance denizens to select it. This must be unique on the instance.
in: formData in: formData
name: shortcode name: shortcode
pattern: \w{2,30} pattern: \w{1,30}
required: true required: true
type: string type: string
- description: A png or gif image of the emoji. Animated pngs work too! To ensure compatibility with other fedi implementations, emoji size limit is 50kb by default. - description: A png or gif image of the emoji. Animated pngs work too! To ensure compatibility with other fedi implementations, emoji size limit is 50kb by default.
@ -5066,7 +5066,7 @@ paths:
- description: The code to use for the emoji, which will be used by instance denizens to select it. This must be unique on the instance. Works for the `copy` action type only. - description: The code to use for the emoji, which will be used by instance denizens to select it. This must be unique on the instance. Works for the `copy` action type only.
in: formData in: formData
name: shortcode name: shortcode
pattern: \w{2,30} pattern: \w{1,30}
type: string type: string
- description: A new png or gif image to use for the emoji. Animated pngs work too! To ensure compatibility with other fedi implementations, emoji size limit is 50kb by default. Works for LOCAL emojis only. - description: A new png or gif image to use for the emoji. Animated pngs work too! To ensure compatibility with other fedi implementations, emoji size limit is 50kb by default. Works for LOCAL emojis only.
in: formData in: formData

View file

@ -53,7 +53,7 @@
// The code to use for the emoji, which will be used by instance denizens to select it. // The code to use for the emoji, which will be used by instance denizens to select it.
// This must be unique on the instance. // This must be unique on the instance.
// type: string // type: string
// pattern: \w{2,30} // pattern: \w{1,30}
// required: true // required: true
// - // -
// name: image // name: image

View file

@ -85,7 +85,7 @@
// The code to use for the emoji, which will be used by instance denizens to select it. // The code to use for the emoji, which will be used by instance denizens to select it.
// This must be unique on the instance. Works for the `copy` action type only. // This must be unique on the instance. Works for the `copy` action type only.
// type: string // type: string
// pattern: \w{2,30} // pattern: \w{1,30}
// - // -
// name: image // name: image
// in: formData // in: formData

View file

@ -560,7 +560,7 @@ func (suite *EmojiUpdateTestSuite) TestEmojiUpdateCopyEmptyShortcode() {
b, err := io.ReadAll(result.Body) b, err := io.ReadAll(result.Body)
suite.NoError(err) suite.NoError(err)
suite.Equal(`{"error":"Bad Request: shortcode did not pass validation, must be between 2 and 30 characters, letters, numbers, and underscores only"}`, string(b)) suite.Equal(`{"error":"Bad Request: shortcode did not pass validation, must be between 1 and 30 characters, letters, numbers, and underscores only"}`, string(b))
} }
func (suite *EmojiUpdateTestSuite) TestEmojiUpdateCopyNoShortcode() { func (suite *EmojiUpdateTestSuite) TestEmojiUpdateCopyNoShortcode() {

View file

@ -155,7 +155,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
}, },
"stats": { "stats": {
"domain_count": 2, "domain_count": 2,
"status_count": 20, "status_count": 19,
"user_count": 4 "user_count": 4
}, },
"thumbnail": "http://localhost:8080/assets/logo.webp", "thumbnail": "http://localhost:8080/assets/logo.webp",
@ -296,7 +296,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
}, },
"stats": { "stats": {
"domain_count": 2, "domain_count": 2,
"status_count": 20, "status_count": 19,
"user_count": 4 "user_count": 4
}, },
"thumbnail": "http://localhost:8080/assets/logo.webp", "thumbnail": "http://localhost:8080/assets/logo.webp",
@ -437,7 +437,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
}, },
"stats": { "stats": {
"domain_count": 2, "domain_count": 2,
"status_count": 20, "status_count": 19,
"user_count": 4 "user_count": 4
}, },
"thumbnail": "http://localhost:8080/assets/logo.webp", "thumbnail": "http://localhost:8080/assets/logo.webp",
@ -629,7 +629,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
}, },
"stats": { "stats": {
"domain_count": 2, "domain_count": 2,
"status_count": 20, "status_count": 19,
"user_count": 4 "user_count": 4
}, },
"thumbnail": "http://localhost:8080/assets/logo.webp", "thumbnail": "http://localhost:8080/assets/logo.webp",
@ -792,7 +792,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
}, },
"stats": { "stats": {
"domain_count": 2, "domain_count": 2,
"status_count": 20, "status_count": 19,
"user_count": 4 "user_count": 4
}, },
"thumbnail": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/original/`+instanceAccount.AvatarMediaAttachment.ID+`.gif",`+` "thumbnail": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/original/`+instanceAccount.AvatarMediaAttachment.ID+`.gif",`+`
@ -974,7 +974,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch9() {
}, },
"stats": { "stats": {
"domain_count": 2, "domain_count": 2,
"status_count": 20, "status_count": 19,
"user_count": 4 "user_count": 4
}, },
"thumbnail": "http://localhost:8080/assets/logo.webp", "thumbnail": "http://localhost:8080/assets/logo.webp",

View file

@ -103,6 +103,9 @@ func (i *instanceDB) CountInstanceStatuses(ctx context.Context, domain string) (
// Ignore statuses that are currently pending approval. // Ignore statuses that are currently pending approval.
q = q.Where("NOT ? = ?", bun.Ident("status.pending_approval"), true) q = q.Where("NOT ? = ?", bun.Ident("status.pending_approval"), true)
// Ignore statuses that are direct messages.
q = q.Where("NOT ? = ?", bun.Ident("status.visibility"), "direct")
count, err := q.Count(ctx) count, err := q.Count(ctx)
if err != nil { if err != nil {
return 0, err return 0, err

View file

@ -47,7 +47,7 @@ func (suite *InstanceTestSuite) TestCountInstanceUsersRemote() {
func (suite *InstanceTestSuite) TestCountInstanceStatuses() { func (suite *InstanceTestSuite) TestCountInstanceStatuses() {
count, err := suite.db.CountInstanceStatuses(context.Background(), config.GetHost()) count, err := suite.db.CountInstanceStatuses(context.Background(), config.GetHost())
suite.NoError(err) suite.NoError(err)
suite.Equal(20, count) suite.Equal(19, count)
} }
func (suite *InstanceTestSuite) TestCountInstanceStatusesRemote() { func (suite *InstanceTestSuite) TestCountInstanceStatusesRemote() {

View file

@ -46,7 +46,7 @@
domainGrp = `(?:` + alphaNumeric + `|\.|\-|\:)` // Non-capturing group that matches against a single valid domain character. domainGrp = `(?:` + alphaNumeric + `|\.|\-|\:)` // Non-capturing group that matches against a single valid domain character.
mentionName = `^@(` + usernameGrp + `+)(?:@(` + domainGrp + `+))?$` // Extract parts of one mention, maybe including domain. mentionName = `^@(` + usernameGrp + `+)(?:@(` + domainGrp + `+))?$` // Extract parts of one mention, maybe including domain.
mentionFinder = `(?:^|\s)(@` + usernameGrp + `+(?:@` + domainGrp + `+)?)` // Extract all mentions from a text, each mention may include domain. mentionFinder = `(?:^|\s)(@` + usernameGrp + `+(?:@` + domainGrp + `+)?)` // Extract all mentions from a text, each mention may include domain.
emojiShortcode = `\w{2,30}` // Pattern for emoji shortcodes. maximumEmojiShortcodeLength = 30 emojiShortcode = `\w{1,30}` // Pattern for emoji shortcodes. maximumEmojiShortcodeLength = 30
emojiFinder = `(?:\b)?:(` + emojiShortcode + `):(?:\b)?` // Extract all emoji shortcodes from a text. emojiFinder = `(?:\b)?:(` + emojiShortcode + `):(?:\b)?` // Extract all emoji shortcodes from a text.
emojiValidator = `^` + emojiShortcode + `$` // Validate a single emoji shortcode. emojiValidator = `^` + emojiShortcode + `$` // Validate a single emoji shortcode.
usernameStrict = `^[a-z0-9_]{1,64}$` // Pattern for usernames on THIS instance. maximumUsernameLength = 64 usernameStrict = `^[a-z0-9_]{1,64}$` // Pattern for usernames on THIS instance. maximumUsernameLength = 64

View file

@ -1993,7 +1993,7 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV1ToFrontend() {
}, },
"stats": { "stats": {
"domain_count": 2, "domain_count": 2,
"status_count": 20, "status_count": 19,
"user_count": 4 "user_count": 4
}, },
"thumbnail": "http://localhost:8080/assets/logo.webp", "thumbnail": "http://localhost:8080/assets/logo.webp",

View file

@ -190,11 +190,11 @@ func CustomCSS(customCSS string) error {
} }
// EmojiShortcode just runs the given shortcode through the regular expression // EmojiShortcode just runs the given shortcode through the regular expression
// for emoji shortcodes, to figure out whether it's a valid shortcode, ie., 2-30 characters, // for emoji shortcodes, to figure out whether it's a valid shortcode, ie., 1-30 characters,
// a-zA-Z, numbers, and underscores. // a-zA-Z, numbers, and underscores.
func EmojiShortcode(shortcode string) error { func EmojiShortcode(shortcode string) error {
if !regexes.EmojiValidator.MatchString(shortcode) { if !regexes.EmojiValidator.MatchString(shortcode) {
return fmt.Errorf("shortcode %s did not pass validation, must be between 2 and 30 characters, letters, numbers, and underscores only", shortcode) return fmt.Errorf("shortcode %s did not pass validation, must be between 1 and 30 characters, letters, numbers, and underscores only", shortcode)
} }
return nil return nil
} }

View file

@ -345,7 +345,7 @@ type testStruct struct {
}, },
{ {
shortcode: "p", shortcode: "p",
ok: false, ok: true,
}, },
{ {
shortcode: "pp", shortcode: "pp",
@ -361,6 +361,10 @@ type testStruct struct {
}, },
{ {
shortcode: "_", shortcode: "_",
ok: true,
},
{
shortcode: "",
ok: false, ok: false,
}, },
{ {

View file

@ -119,7 +119,7 @@ export default function NewEmojiForm() {
label="Shortcode, must be unique among the instance's local emoji" label="Shortcode, must be unique among the instance's local emoji"
autoCapitalize="none" autoCapitalize="none"
spellCheck="false" spellCheck="false"
{...{pattern: "^\\w{2,30}$"}} {...{pattern: "^\\w{1,30}$"}}
/> />
<CategorySelect <CategorySelect

View file

@ -22,7 +22,7 @@ import { useMemo } from "react";
import { useTextInput } from "../../../../lib/form"; import { useTextInput } from "../../../../lib/form";
import { useListEmojiQuery } from "../../../../lib/query/admin/custom-emoji"; import { useListEmojiQuery } from "../../../../lib/query/admin/custom-emoji";
const shortcodeRegex = /^\w{2,30}$/; const shortcodeRegex = /^\w{1,30}$/;
export default function useShortcode() { export default function useShortcode() {
const { data: emoji = [] } = useListEmojiQuery({ const { data: emoji = [] } = useListEmojiQuery({
@ -42,8 +42,8 @@ export default function useShortcode() {
return "Shortcode already in use"; return "Shortcode already in use";
} }
if (code.length < 2 || code.length > 30) { if (code.length < 1 || code.length > 30) {
return "Shortcode must be between 2 and 30 characters"; return "Shortcode must be between 1 and 30 characters";
} }
if (!shortcodeRegex.test(code)) { if (!shortcodeRegex.test(code)) {

View file

@ -2922,9 +2922,9 @@ create-require@^1.1.0:
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cross-spawn@^7.0.2: cross-spawn@^7.0.2:
version "7.0.3" version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
dependencies: dependencies:
path-key "^3.1.0" path-key "^3.1.0"
shebang-command "^2.0.0" shebang-command "^2.0.0"