Received: from mail.netlandish.com (mail.netlandish.com [174.136.98.166]) by code.netlandish.com (Postfix) with ESMTP id 5DD13163 for <~netlandish/links-dev@lists.code.netlandish.com>; Thu, 19 Jun 2025 01:02:45 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.219.180; helo=mail-yb1-f180.google.com; envelope-from=peter@netlandish.com; receiver= Authentication-Results: mail.netlandish.com; dkim=pass (1024-bit key; unprotected) header.d=netlandish.com header.i=@netlandish.com header.b=jVWxiwiW Received: from mail-yb1-f180.google.com (mail-yb1-f180.google.com [209.85.219.180]) by mail.netlandish.com (Postfix) with ESMTP id B1C571D642E for <~netlandish/links-dev@lists.code.netlandish.com>; Thu, 19 Jun 2025 01:03:15 +0000 (UTC) Received: by mail-yb1-f180.google.com with SMTP id 3f1490d57ef6-e7311e66a8eso306547276.2 for <~netlandish/links-dev@lists.code.netlandish.com>; Wed, 18 Jun 2025 18:03:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netlandish.com; s=google; t=1750294995; x=1750899795; darn=lists.code.netlandish.com; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Cy/KsTA3vyiVfdhsSWQvefDfyEQNFfyrbMmeJrH39kM=; b=jVWxiwiW2xdp7Hc6PjH4aBnQphDGNXNR9tYKzdqo0FTgIhhdY0vA6qvi4zonWpGCjN 2q+WS1wL28aHPePE1qyN82Q9afsLb5No4JLmkVJ0Qksx3ZZHSCgWlWd1KhM7iFj7SNyN H4/iJbr5q4qPvISBOQTuN2CYZAHCaxfqUgsl4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750294995; x=1750899795; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Cy/KsTA3vyiVfdhsSWQvefDfyEQNFfyrbMmeJrH39kM=; b=jwMK8dT8Vn6tfwdYLbcBqOJ5zjOrVFHeKLPoZAm5OcHd5uH7TDTZr406uf0RLgdLU7 OxM/+49ZTlt0EsAlsjrwNveReN0PvWFfT4z4bwY+DCNH3LheIAU8E8Eyb78r3Mue98Qg FISoXO3eAaaGiZLzRf3Mly0HrQZn6TAbw3ERhu/Axv9j0Laajr4hpM7lnnj8as/6knwy mM5WiRSTarVy9vsWmrCWKODCQllWGoEo8f57yCzpexEzu+BJDRnSpTjWZzPtybAnZVJR aItEm01bzWDwSoNZUjX+0IwVDUU+rgBmwA8pTRJtJT2MX7lN2aw4WGEUqdD1ERPNALGj TWYg== X-Gm-Message-State: AOJu0Yw6hMe32h5vp7QrL9ZaY8GooT7317YBg5kw5Nh5UkpPp7ZrI0jE dq5Bcleog0HgxZSSwij5Sri/7FSzMRtG3I/otD8WX8SYJvoORsliJbDnb+2W7nkXJf1jP/6it1d hhmCKIvM= X-Gm-Gg: ASbGncvZZ40LOZWoJ2YAjvlEbaAKLZl/4uao0mk7KUzfzQbKmcBBeymAcULhJ35Bxu2 NtyiSqJXZ07PvlmGaKBkIWT3I4xMdgsc3ORbXih47eQX8VsB64Ca92b9GcguAXdX1FvSeB53reZ rcHCe0iONOl3nRwwgUYbaWTAaKqp7hZnd5zaXiRHMQtgi1Kq/wudB0sqzbeHfFbKCLz/5Mqp3F+ 4xMZWBD9NAdB0Sb4O3M1YF1sXMH/f2HTzgryN05c4Z9KmkFCdL8TN/AVXwSaopmef8q1HuGfBYr 4O6E6SKFKoOWcR4xn/+GF1DNWOajX7DJm+rLerIToPpXEEzCrYUxan7lsJw+Z/w= X-Google-Smtp-Source: AGHT+IG7FLLQXqjcxfDlPR1joLl55RbmsX35tUuXgSABVQhHrMAHltUWNPJQdZ9oXZwVs+V9OjeB+w== X-Received: by 2002:a05:690c:f07:b0:70c:9478:6090 with SMTP id 00721157ae682-7117544ca4amr265942977b3.28.1750294993604; Wed, 18 Jun 2025 18:03:13 -0700 (PDT) Received: from localhost ([2803:2d60:1118:5ee:765d:da50:e7f5:580b]) by smtp.gmail.com with ESMTPSA id 00721157ae682-712b7b97a44sm819747b3.82.2025.06.18.18.03.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Jun 2025 18:03:12 -0700 (PDT) From: Peter Sanchez To: ~netlandish/links-dev@lists.code.netlandish.com Cc: Peter Sanchez Subject: [PATCH links] Adding a new `visibility` flag for organizations and specific base urls. This is to hide the obvious spam or SEO farms from the recent or popular pages. Date: Wed, 18 Jun 2025 19:03:04 -0600 Message-ID: <20250619010309.2870-1-peter@netlandish.com> X-Mailer: git-send-email 2.47.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changelog-added: Ability to hide spammers or seo farms from the recent or popular pages. Changelog-updated: API version (minor bump) to account for new visibility variable and update to (admin only) organization update mutation. --- admin/input.go | 4 +- admin/routes.go | 35 +- api/graph/generated.go | 404 ++- api/graph/model/models_gen.go | 47 + api/graph/schema.graphqls | 14 +- api/graph/schema.resolvers.go | 74 +- api/loaders/loaders.go | 3 + client.go | 2 +- cmd/migrations.go | 7 + internal/translations/catalog.go | 2211 +++++++++-------- .../translations/locales/en/out.gotext.json | 7 + .../locales/es/messages.gotext.json | 5 + .../translations/locales/es/out.gotext.json | 5 + .../0007_add_base_org_visibility.down.sql | 4 + .../0007_add_base_org_visibility.up.sql | 4 + models/base_url.go | 12 +- models/models.go | 24 +- models/organization.go | 23 +- models/schema.sql | 7 + templates/admin_org_detail.html | 4 + templates/admin_update_org_type.html | 15 +- 21 files changed, 1683 insertions(+), 1228 deletions(-) create mode 100644 migrations/0007_add_base_org_visibility.down.sql create mode 100644 migrations/0007_add_base_org_visibility.up.sql diff --git a/admin/input.go b/admin/input.go index 7918875..6f4b94b 100644 --- a/admin/input.go +++ b/admin/input.go @@ -85,13 +85,15 @@ func (d *DomainForm) Validate(c echo.Context) error { } type OrgTypeForm struct { - OrgType string `form:"org_type" validate:"oneof=FREE PERSONAL BUSINESS OPEN_SOURCE SPONSORED"` + OrgType string `form:"org_type" validate:"oneof=FREE PERSONAL BUSINESS OPEN_SOURCE SPONSORED"` + Visibility string `form:"visibility" validate:"oneof=PUBLIC HIDDEN"` } func (ot *OrgTypeForm) Validate(c echo.Context) error { errs := validate.FormFieldBinder(c, ot). FailFast(false). String("org_type", &ot.OrgType). + String("visibility", &ot.Visibility). BindErrors() if errs != nil { return validate.GetInputErrors(errs) diff --git a/admin/routes.go b/admin/routes.go index d6f30a8..8d42781 100644 --- a/admin/routes.go +++ b/admin/routes.go @@ -244,12 +244,13 @@ func (s *Service) UpdateOrgType(c echo.Context) error { return echo.NotFoundHandler(c) } lt := localizer.GetSessionLocalizer(c) - pd := localizer.NewPageData(lt.Translate("Update Organization Type")) + pd := localizer.NewPageData(lt.Translate("Update Organization")) pd.Data["for"] = lt.Translate("for") pd.Data["type"] = lt.Translate("Type") pd.Data["back"] = lt.Translate("Back") pd.Data["save"] = lt.Translate("Save") pd.Data["cancel"] = lt.Translate("Cancel") + pd.Data["visibility"] = lt.Translate("Visibility") orgTypes := map[string]string{ models.BillingStatusFree: lt.Translate("Free"), @@ -258,6 +259,10 @@ func (s *Service) UpdateOrgType(c echo.Context) error { models.BillingStatusOpenSource: lt.Translate("Open Source"), models.BillingStatusSponsored: lt.Translate("Sponsored"), } + visOpts := map[string]string{ + models.VisibilityPublic: lt.Translate("PUBLIC"), + models.VisibilityHidden: lt.Translate("HIDDEN"), + } type GraphQLResponse struct { Org *models.Organization `json:"getOrganization"` @@ -269,6 +274,7 @@ func (s *Service) UpdateOrgType(c echo.Context) error { id name slug + visibility settings { billing { status @@ -282,13 +288,17 @@ func (s *Service) UpdateOrgType(c echo.Context) error { return err } - form := &OrgTypeForm{} + form := &OrgTypeForm{ + OrgType: result.Org.Settings.Billing.Status, + Visibility: result.Org.Visibility, + } gmap := gobwebs.Map{ "pd": pd, "navFlag": "admin", "org": result.Org, "form": form, "orgTypes": orgTypes, + "visOpts": visOpts, } req := c.Request() if req.Method == http.MethodPost { @@ -303,19 +313,28 @@ func (s *Service) UpdateOrgType(c echo.Context) error { } } type GraphQLUpdatedResponse struct { - Org *models.Organization `json:"updateAdminOrgType"` + Org *models.Organization `json:"updateAdminOrg"` } var resultUpdated GraphQLUpdatedResponse op = gqlclient.NewOperation(` - mutation UpdateAdminOrgType($orgSlug: String!, $orgType: OrgBillingStatus!) { - updateAdminOrgType(orgSlug: $orgSlug, orgType: $orgType) { + mutation UpdateAdminOrg($orgSlug: String!, $orgType: OrgBillingStatus, $visibility: PublicVisibility) { + updateAdminOrg(input: { + orgSlug: $orgSlug, + orgType: $orgType, + visibility: $visibility + }) { id slug } } `) op.Var("orgSlug", result.Org.Slug) - op.Var("orgType", form.OrgType) + if form.OrgType != "" { + op.Var("orgType", form.OrgType) + } + if form.Visibility != "" { + op.Var("visibility", form.Visibility) + } err = links.Execute(c.Request().Context(), op, &resultUpdated) if err != nil { return err @@ -374,6 +393,7 @@ func (s *Service) OrgDetail(c echo.Context) error { pd.Data["service"] = lt.Translate("Service") pd.Data["no_domains"] = lt.Translate("No Domains") pd.Data["update_type"] = lt.Translate("Update Type") + pd.Data["visibility"] = lt.Translate("Visibility") type GraphQLResponse struct { Org *models.Organization `json:"getOrganization"` @@ -387,6 +407,7 @@ func (s *Service) OrgDetail(c echo.Context) error { slug createdOn isActive + visibility settings { billing { status @@ -418,7 +439,7 @@ func (s *Service) OrgDetail(c echo.Context) error { op = gqlclient.NewOperation( `query GetPaymentHistory($orgSlug: String, $after: Cursor, $before: Cursor) { getPaymentHistory(input: { - orgSlug: $orgSlug + orgSlug: $orgSlug, after: $after, before: $before, }) { diff --git a/api/graph/generated.go b/api/graph/generated.go index ff56a5e..c0901b0 100644 --- a/api/graph/generated.go +++ b/api/graph/generated.go @@ -43,6 +43,7 @@ type Config struct { type ResolverRoot interface { AuditLog() AuditLogResolver + BaseURL() BaseURLResolver BillingSettings() BillingSettingsResolver Domain() DomainResolver Mutation() MutationResolver @@ -120,6 +121,7 @@ type ComplexityRoot struct { Title func(childComplexity int) int URL func(childComplexity int) int UpdatedOn func(childComplexity int) int + Visibility func(childComplexity int) int } BaseURLData struct { @@ -265,7 +267,7 @@ type ComplexityRoot struct { SendRegisterInvitation func(childComplexity int, toEmail string) int Unfollow func(childComplexity int, orgSlug string) int UpdateAdminDomain func(childComplexity int, input model.UpdateAdminDomainInput) int - UpdateAdminOrgType func(childComplexity int, orgSlug string, orgType model.OrgBillingStatus) int + UpdateAdminOrg func(childComplexity int, input model.AdminUpdateOrgInput) int UpdateAdminUser func(childComplexity int, input *model.UpdateUserInput) int UpdateLink func(childComplexity int, input *model.UpdateLinkInput) int UpdateLinkShort func(childComplexity int, input *model.UpdateLinkShortInput) int @@ -317,18 +319,19 @@ type ComplexityRoot struct { } Organization struct { - CreatedOn func(childComplexity int) int - ID func(childComplexity int) int - Image func(childComplexity int) int - IsActive func(childComplexity int) int - Name func(childComplexity int) int - OrgType func(childComplexity int) int - OwnerID func(childComplexity int) int - OwnerName func(childComplexity int) int - Settings func(childComplexity int) int - Slug func(childComplexity int) int - Timezone func(childComplexity int) int - UpdatedOn func(childComplexity int) int + CreatedOn func(childComplexity int) int + ID func(childComplexity int) int + Image func(childComplexity int) int + IsActive func(childComplexity int) int + Name func(childComplexity int) int + OrgType func(childComplexity int) int + OwnerID func(childComplexity int) int + OwnerName func(childComplexity int) int + Settings func(childComplexity int) int + Slug func(childComplexity int) int + Timezone func(childComplexity int) int + UpdatedOn func(childComplexity int) int + Visibility func(childComplexity int) int } OrganizationCursor struct { @@ -476,6 +479,9 @@ type ComplexityRoot struct { type AuditLogResolver interface { Metadata(ctx context.Context, obj *auditlog.AuditLog) (map[string]interface{}, error) } +type BaseURLResolver interface { + Visibility(ctx context.Context, obj *models.BaseURL) (model.PublicVisibility, error) +} type BillingSettingsResolver interface { Status(ctx context.Context, obj *models.BillingSettings) (model.OrgBillingStatus, error) } @@ -514,7 +520,7 @@ type MutationResolver interface { DeleteQRCode(ctx context.Context, id int) (*model.DeletePayload, error) Follow(ctx context.Context, orgSlug string) (*model.FollowPayload, error) Unfollow(ctx context.Context, orgSlug string) (*model.FollowPayload, error) - UpdateAdminOrgType(ctx context.Context, orgSlug string, orgType model.OrgBillingStatus) (*models.Organization, error) + UpdateAdminOrg(ctx context.Context, input model.AdminUpdateOrgInput) (*models.Organization, error) AddAdminDomain(ctx context.Context, input model.AdminDomainInput) (*models.Domain, error) UpdateAdminDomain(ctx context.Context, input model.UpdateAdminDomainInput) (*models.Domain, error) UpdateAdminUser(ctx context.Context, input *model.UpdateUserInput) (*models.User, error) @@ -529,6 +535,8 @@ type OrganizationResolver interface { OrgType(ctx context.Context, obj *models.Organization) (model.OrgType, error) Image(ctx context.Context, obj *models.Organization) (*graphql.Upload, error) + + Visibility(ctx context.Context, obj *models.Organization) (model.PublicVisibility, error) } type OrganizationSettingsResolver interface { DefaultPerm(ctx context.Context, obj *models.OrganizationSettings) (model.LinkVisibility, error) @@ -856,6 +864,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.BaseURL.UpdatedOn(childComplexity), true + case "BaseURL.visibility": + if e.complexity.BaseURL.Visibility == nil { + break + } + + return e.complexity.BaseURL.Visibility(childComplexity), true + case "BaseURLData.meta": if e.complexity.BaseURLData.Meta == nil { break @@ -1655,17 +1670,17 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.UpdateAdminDomain(childComplexity, args["input"].(model.UpdateAdminDomainInput)), true - case "Mutation.updateAdminOrgType": - if e.complexity.Mutation.UpdateAdminOrgType == nil { + case "Mutation.updateAdminOrg": + if e.complexity.Mutation.UpdateAdminOrg == nil { break } - args, err := ec.field_Mutation_updateAdminOrgType_args(context.TODO(), rawArgs) + args, err := ec.field_Mutation_updateAdminOrg_args(context.TODO(), rawArgs) if err != nil { return 0, false } - return e.complexity.Mutation.UpdateAdminOrgType(childComplexity, args["orgSlug"].(string), args["orgType"].(model.OrgBillingStatus)), true + return e.complexity.Mutation.UpdateAdminOrg(childComplexity, args["input"].(model.AdminUpdateOrgInput)), true case "Mutation.updateAdminUser": if e.complexity.Mutation.UpdateAdminUser == nil { @@ -2038,6 +2053,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Organization.UpdatedOn(childComplexity), true + case "Organization.visibility": + if e.complexity.Organization.Visibility == nil { + break + } + + return e.complexity.Organization.Visibility(childComplexity), true + case "OrganizationCursor.pageInfo": if e.complexity.OrganizationCursor.PageInfo == nil { break @@ -2832,6 +2854,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputAddQRCodeInput, ec.unmarshalInputAdminBillingInput, ec.unmarshalInputAdminDomainInput, + ec.unmarshalInputAdminUpdateOrgInput, ec.unmarshalInputAnalyticsInput, ec.unmarshalInputAuditLogInput, ec.unmarshalInputCompleteRegisterInput, @@ -3863,62 +3886,35 @@ func (ec *executionContext) field_Mutation_updateAdminDomain_argsInput( return zeroVal, nil } -func (ec *executionContext) field_Mutation_updateAdminOrgType_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { +func (ec *executionContext) field_Mutation_updateAdminOrg_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - arg0, err := ec.field_Mutation_updateAdminOrgType_argsOrgSlug(ctx, rawArgs) + arg0, err := ec.field_Mutation_updateAdminOrg_argsInput(ctx, rawArgs) if err != nil { return nil, err } - args["orgSlug"] = arg0 - arg1, err := ec.field_Mutation_updateAdminOrgType_argsOrgType(ctx, rawArgs) - if err != nil { - return nil, err - } - args["orgType"] = arg1 + args["input"] = arg0 return args, nil } -func (ec *executionContext) field_Mutation_updateAdminOrgType_argsOrgSlug( +func (ec *executionContext) field_Mutation_updateAdminOrg_argsInput( ctx context.Context, rawArgs map[string]interface{}, -) (string, error) { +) (model.AdminUpdateOrgInput, error) { // We won't call the directive if the argument is null. // Set call_argument_directives_with_null to true to call directives // even if the argument is null. - _, ok := rawArgs["orgSlug"] + _, ok := rawArgs["input"] if !ok { - var zeroVal string + var zeroVal model.AdminUpdateOrgInput return zeroVal, nil } - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("orgSlug")) - if tmp, ok := rawArgs["orgSlug"]; ok { - return ec.unmarshalNString2string(ctx, tmp) + ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + if tmp, ok := rawArgs["input"]; ok { + return ec.unmarshalNAdminUpdateOrgInput2linksᚋapiᚋgraphᚋmodelᚐAdminUpdateOrgInput(ctx, tmp) } - var zeroVal string - return zeroVal, nil -} - -func (ec *executionContext) field_Mutation_updateAdminOrgType_argsOrgType( - ctx context.Context, - rawArgs map[string]interface{}, -) (model.OrgBillingStatus, error) { - // We won't call the directive if the argument is null. - // Set call_argument_directives_with_null to true to call directives - // even if the argument is null. - _, ok := rawArgs["orgType"] - if !ok { - var zeroVal model.OrgBillingStatus - return zeroVal, nil - } - - ctx = graphql.WithPathContext(ctx, graphql.NewPathWithField("orgType")) - if tmp, ok := rawArgs["orgType"]; ok { - return ec.unmarshalNOrgBillingStatus2linksᚋapiᚋgraphᚋmodelᚐOrgBillingStatus(ctx, tmp) - } - - var zeroVal model.OrgBillingStatus + var zeroVal model.AdminUpdateOrgInput return zeroVal, nil } @@ -6996,6 +6992,50 @@ func (ec *executionContext) fieldContext_BaseURL_data(_ context.Context, field g return fc, nil } +func (ec *executionContext) _BaseURL_visibility(ctx context.Context, field graphql.CollectedField, obj *models.BaseURL) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BaseURL_visibility(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.BaseURL().Visibility(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.PublicVisibility) + fc.Result = res + return ec.marshalNPublicVisibility2linksᚋapiᚋgraphᚋmodelᚐPublicVisibility(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_BaseURL_visibility(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "BaseURL", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type PublicVisibility does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _BaseURL_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.BaseURL) (ret graphql.Marshaler) { fc, err := ec.fieldContext_BaseURL_createdOn(ctx, field) if err != nil { @@ -11343,6 +11383,8 @@ func (ec *executionContext) fieldContext_Mutation_addOrganization(ctx context.Co return ec.fieldContext_Organization_settings(ctx, field) case "isActive": return ec.fieldContext_Organization_isActive(ctx, field) + case "visibility": + return ec.fieldContext_Organization_visibility(ctx, field) case "createdOn": return ec.fieldContext_Organization_createdOn(ctx, field) case "updatedOn": @@ -11456,6 +11498,8 @@ func (ec *executionContext) fieldContext_Mutation_updateOrganization(ctx context return ec.fieldContext_Organization_settings(ctx, field) case "isActive": return ec.fieldContext_Organization_isActive(ctx, field) + case "visibility": + return ec.fieldContext_Organization_visibility(ctx, field) case "createdOn": return ec.fieldContext_Organization_createdOn(ctx, field) case "updatedOn": @@ -14099,8 +14143,8 @@ func (ec *executionContext) fieldContext_Mutation_unfollow(ctx context.Context, return fc, nil } -func (ec *executionContext) _Mutation_updateAdminOrgType(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Mutation_updateAdminOrgType(ctx, field) +func (ec *executionContext) _Mutation_updateAdminOrg(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_updateAdminOrg(ctx, field) if err != nil { return graphql.Null } @@ -14114,7 +14158,7 @@ func (ec *executionContext) _Mutation_updateAdminOrgType(ctx context.Context, fi resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().UpdateAdminOrgType(rctx, fc.Args["orgSlug"].(string), fc.Args["orgType"].(model.OrgBillingStatus)) + return ec.resolvers.Mutation().UpdateAdminOrg(rctx, fc.Args["input"].(model.AdminUpdateOrgInput)) } directive1 := func(ctx context.Context) (interface{}, error) { @@ -14152,7 +14196,7 @@ func (ec *executionContext) _Mutation_updateAdminOrgType(ctx context.Context, fi return ec.marshalNOrganization2ᚖlinksᚋmodelsᚐOrganization(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Mutation_updateAdminOrgType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Mutation_updateAdminOrg(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ Object: "Mutation", Field: field, @@ -14178,6 +14222,8 @@ func (ec *executionContext) fieldContext_Mutation_updateAdminOrgType(ctx context return ec.fieldContext_Organization_settings(ctx, field) case "isActive": return ec.fieldContext_Organization_isActive(ctx, field) + case "visibility": + return ec.fieldContext_Organization_visibility(ctx, field) case "createdOn": return ec.fieldContext_Organization_createdOn(ctx, field) case "updatedOn": @@ -14195,7 +14241,7 @@ func (ec *executionContext) fieldContext_Mutation_updateAdminOrgType(ctx context } }() ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Mutation_updateAdminOrgType_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + if fc.Args, err = ec.field_Mutation_updateAdminOrg_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) return fc, err } @@ -16673,6 +16719,50 @@ func (ec *executionContext) fieldContext_Organization_isActive(_ context.Context return fc, nil } +func (ec *executionContext) _Organization_visibility(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Organization_visibility(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Organization().Visibility(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(model.PublicVisibility) + fc.Result = res + return ec.marshalNPublicVisibility2linksᚋapiᚋgraphᚋmodelᚐPublicVisibility(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Organization_visibility(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Organization", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type PublicVisibility does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Organization_createdOn(ctx context.Context, field graphql.CollectedField, obj *models.Organization) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Organization_createdOn(ctx, field) if err != nil { @@ -16894,6 +16984,8 @@ func (ec *executionContext) fieldContext_OrganizationCursor_result(_ context.Con return ec.fieldContext_Organization_settings(ctx, field) case "isActive": return ec.fieldContext_Organization_isActive(ctx, field) + case "visibility": + return ec.fieldContext_Organization_visibility(ctx, field) case "createdOn": return ec.fieldContext_Organization_createdOn(ctx, field) case "updatedOn": @@ -18005,6 +18097,8 @@ func (ec *executionContext) fieldContext_PopularLinkCursor_result(_ context.Cont return ec.fieldContext_BaseURL_hash(ctx, field) case "data": return ec.fieldContext_BaseURL_data(ctx, field) + case "visibility": + return ec.fieldContext_BaseURL_visibility(ctx, field) case "createdOn": return ec.fieldContext_BaseURL_createdOn(ctx, field) case "updatedOn": @@ -19048,6 +19142,8 @@ func (ec *executionContext) fieldContext_Query_getOrganizations(ctx context.Cont return ec.fieldContext_Organization_settings(ctx, field) case "isActive": return ec.fieldContext_Organization_isActive(ctx, field) + case "visibility": + return ec.fieldContext_Organization_visibility(ctx, field) case "createdOn": return ec.fieldContext_Organization_createdOn(ctx, field) case "updatedOn": @@ -19158,6 +19254,8 @@ func (ec *executionContext) fieldContext_Query_getOrganization(ctx context.Conte return ec.fieldContext_Organization_settings(ctx, field) case "isActive": return ec.fieldContext_Organization_isActive(ctx, field) + case "visibility": + return ec.fieldContext_Organization_visibility(ctx, field) case "createdOn": return ec.fieldContext_Organization_createdOn(ctx, field) case "updatedOn": @@ -21017,6 +21115,8 @@ func (ec *executionContext) fieldContext_Query_getFeedFollowing(_ context.Contex return ec.fieldContext_Organization_settings(ctx, field) case "isActive": return ec.fieldContext_Organization_isActive(ctx, field) + case "visibility": + return ec.fieldContext_Organization_visibility(ctx, field) case "createdOn": return ec.fieldContext_Organization_createdOn(ctx, field) case "updatedOn": @@ -25172,6 +25272,47 @@ func (ec *executionContext) unmarshalInputAdminDomainInput(ctx context.Context, return it, nil } +func (ec *executionContext) unmarshalInputAdminUpdateOrgInput(ctx context.Context, obj interface{}) (model.AdminUpdateOrgInput, error) { + var it model.AdminUpdateOrgInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"orgSlug", "orgType", "visibility"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "orgSlug": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("orgSlug")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.OrgSlug = data + case "orgType": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("orgType")) + data, err := ec.unmarshalOOrgBillingStatus2ᚖlinksᚋapiᚋgraphᚋmodelᚐOrgBillingStatus(ctx, v) + if err != nil { + return it, err + } + it.OrgType = data + case "visibility": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("visibility")) + data, err := ec.unmarshalOPublicVisibility2ᚖlinksᚋapiᚋgraphᚋmodelᚐPublicVisibility(ctx, v) + if err != nil { + return it, err + } + it.Visibility = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputAnalyticsInput(ctx context.Context, obj interface{}) (model.AnalyticsInput, error) { var it model.AnalyticsInput asMap := map[string]interface{}{} @@ -27456,49 +27597,85 @@ func (ec *executionContext) _BaseURL(ctx context.Context, sel ast.SelectionSet, case "id": out.Values[i] = ec._BaseURL_id(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "title": out.Values[i] = ec._BaseURL_title(ctx, field, obj) case "url": out.Values[i] = ec._BaseURL_url(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "counter": out.Values[i] = ec._BaseURL_counter(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "tags": out.Values[i] = ec._BaseURL_tags(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "publicReady": out.Values[i] = ec._BaseURL_publicReady(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "hash": out.Values[i] = ec._BaseURL_hash(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "data": out.Values[i] = ec._BaseURL_data(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } + case "visibility": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._BaseURL_visibility(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "createdOn": out.Values[i] = ec._BaseURL_createdOn(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } case "updatedOn": out.Values[i] = ec._BaseURL_updatedOn(ctx, field, obj) if out.Values[i] == graphql.Null { - out.Invalids++ + atomic.AddUint32(&out.Invalids, 1) } default: panic("unknown field " + strconv.Quote(field.Name)) @@ -28762,9 +28939,9 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) if out.Values[i] == graphql.Null { out.Invalids++ } - case "updateAdminOrgType": + case "updateAdminOrg": out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { - return ec._Mutation_updateAdminOrgType(ctx, field) + return ec._Mutation_updateAdminOrg(ctx, field) }) if out.Values[i] == graphql.Null { out.Invalids++ @@ -29266,6 +29443,42 @@ func (ec *executionContext) _Organization(ctx context.Context, sel ast.Selection if out.Values[i] == graphql.Null { atomic.AddUint32(&out.Invalids, 1) } + case "visibility": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Organization_visibility(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "createdOn": out.Values[i] = ec._Organization_createdOn(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -31251,6 +31464,11 @@ func (ec *executionContext) unmarshalNAdminDomainInput2linksᚋapiᚋgraphᚋmod return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNAdminUpdateOrgInput2linksᚋapiᚋgraphᚋmodelᚐAdminUpdateOrgInput(ctx context.Context, v interface{}) (model.AdminUpdateOrgInput, error) { + res, err := ec.unmarshalInputAdminUpdateOrgInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNAnalyticData2ᚕᚖlinksᚋapiᚋgraphᚋmodelᚐAnalyticData(ctx context.Context, sel ast.SelectionSet, v []*model.AnalyticData) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -32145,6 +32363,16 @@ func (ec *executionContext) marshalNPopularLinkCursor2ᚖlinksᚋapiᚋgraphᚋm return ec._PopularLinkCursor(ctx, sel, v) } +func (ec *executionContext) unmarshalNPublicVisibility2linksᚋapiᚋgraphᚋmodelᚐPublicVisibility(ctx context.Context, v interface{}) (model.PublicVisibility, error) { + var res model.PublicVisibility + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNPublicVisibility2linksᚋapiᚋgraphᚋmodelᚐPublicVisibility(ctx context.Context, sel ast.SelectionSet, v model.PublicVisibility) graphql.Marshaler { + return v +} + func (ec *executionContext) marshalNQRCode2linksᚋmodelsᚐQRCode(ctx context.Context, sel ast.SelectionSet, v models.QRCode) graphql.Marshaler { return ec._QRCode(ctx, sel, &v) } @@ -33061,6 +33289,22 @@ func (ec *executionContext) marshalOOrderType2ᚖlinksᚋapiᚋgraphᚋmodelᚐO return v } +func (ec *executionContext) unmarshalOOrgBillingStatus2ᚖlinksᚋapiᚋgraphᚋmodelᚐOrgBillingStatus(ctx context.Context, v interface{}) (*model.OrgBillingStatus, error) { + if v == nil { + return nil, nil + } + var res = new(model.OrgBillingStatus) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOOrgBillingStatus2ᚖlinksᚋapiᚋgraphᚋmodelᚐOrgBillingStatus(ctx context.Context, sel ast.SelectionSet, v *model.OrgBillingStatus) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + func (ec *executionContext) marshalOOrgLink2ᚖlinksᚋmodelsᚐOrgLink(ctx context.Context, sel ast.SelectionSet, v *models.OrgLink) graphql.Marshaler { if v == nil { return graphql.Null @@ -33105,6 +33349,22 @@ func (ec *executionContext) unmarshalOProfileInput2ᚖlinksᚋapiᚋgraphᚋmode return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalOPublicVisibility2ᚖlinksᚋapiᚋgraphᚋmodelᚐPublicVisibility(ctx context.Context, v interface{}) (*model.PublicVisibility, error) { + if v == nil { + return nil, nil + } + var res = new(model.PublicVisibility) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOPublicVisibility2ᚖlinksᚋapiᚋgraphᚋmodelᚐPublicVisibility(ctx context.Context, sel ast.SelectionSet, v *model.PublicVisibility) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + func (ec *executionContext) marshalOQRCode2ᚕᚖlinksᚋmodelsᚐQRCode(ctx context.Context, sel ast.SelectionSet, v []*models.QRCode) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/api/graph/model/models_gen.go b/api/graph/model/models_gen.go index 1d9c463..065ae14 100644 --- a/api/graph/model/models_gen.go +++ b/api/graph/model/models_gen.go @@ -81,6 +81,12 @@ type AdminDomainInput struct { MigrateLinks *bool `json:"migrateLinks,omitempty"` } +type AdminUpdateOrgInput struct { + OrgSlug string `json:"orgSlug"` + OrgType *OrgBillingStatus `json:"orgType,omitempty"` + Visibility *PublicVisibility `json:"visibility,omitempty"` +} + type AnalyticData struct { Key string `json:"key"` Val int `json:"val"` @@ -1070,6 +1076,47 @@ func (e OrgType) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } +type PublicVisibility string + +const ( + PublicVisibilityPublic PublicVisibility = "PUBLIC" + PublicVisibilityHidden PublicVisibility = "HIDDEN" +) + +var AllPublicVisibility = []PublicVisibility{ + PublicVisibilityPublic, + PublicVisibilityHidden, +} + +func (e PublicVisibility) IsValid() bool { + switch e { + case PublicVisibilityPublic, PublicVisibilityHidden: + return true + } + return false +} + +func (e PublicVisibility) String() string { + return string(e) +} + +func (e *PublicVisibility) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = PublicVisibility(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid PublicVisibility", str) + } + return nil +} + +func (e PublicVisibility) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + type QRCodeType string const ( diff --git a/api/graph/schema.graphqls b/api/graph/schema.graphqls index adfa596..ea8c48a 100644 --- a/api/graph/schema.graphqls +++ b/api/graph/schema.graphqls @@ -133,6 +133,10 @@ enum OrderType { ASC } +enum PublicVisibility { + PUBLIC + HIDDEN +} # Considering removing these Null* fields: # https://todo.code.netlandish.com/~netlandish/links/75 @@ -179,6 +183,7 @@ type Organization { timezone: String! @access(scope: ORGS, kind: RO) settings: OrganizationSettings! @access(scope: ORGS, kind: RO) isActive: Boolean! @access(scope: ORGS, kind: RO) + visibility: PublicVisibility! createdOn: Time! updatedOn: Time! ownerName: String! @access(scope: ORGS, kind: RO) @@ -217,6 +222,7 @@ type BaseURL { publicReady: Boolean! @internal hash: String! data: BaseURLData! + visibility: PublicVisibility! createdOn: Time! updatedOn: Time! } @@ -800,6 +806,12 @@ input AuditLogInput { limit: Int } +input AdminUpdateOrgInput { + orgSlug: String! + orgType: OrgBillingStatus + visibility: PublicVisibility +} + type Query { "Returns API version information." version: Version! @@ -938,7 +950,7 @@ type Mutation { # Admin only. Not open to public calls # - updateAdminOrgType(orgSlug: String!, orgType: OrgBillingStatus!): Organization! @admin + updateAdminOrg(input: AdminUpdateOrgInput!): Organization! @admin addAdminDomain(input: AdminDomainInput!): Domain! @admin updateAdminDomain(input: UpdateAdminDomainInput!): Domain! @admin updateAdminUser(input: UpdateUserInput): User! @admin diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go index 8bd3f3d..956e692 100644 --- a/api/graph/schema.resolvers.go +++ b/api/graph/schema.resolvers.go @@ -58,6 +58,11 @@ func (r *auditLogResolver) Metadata(ctx context.Context, obj *auditlog.AuditLog) return obj.Metadata, nil } +// Visibility is the resolver for the visibility field. +func (r *baseURLResolver) Visibility(ctx context.Context, obj *models.BaseURL) (model.PublicVisibility, error) { + return model.PublicVisibility(obj.Visibility), nil +} + // Status is the resolver for the status field. func (r *billingSettingsResolver) Status(ctx context.Context, obj *models.BillingSettings) (model.OrgBillingStatus, error) { return model.OrgBillingStatus(obj.Status), nil @@ -4184,7 +4189,7 @@ func (r *mutationResolver) Unfollow(ctx context.Context, orgSlug string) (*model } // UpdateAdminOrgType is the resolver for the updateAdminOrgType field. -func (r *mutationResolver) UpdateAdminOrgType(ctx context.Context, orgSlug string, orgType model.OrgBillingStatus) (*models.Organization, error) { +func (r *mutationResolver) UpdateAdminOrg(ctx context.Context, input model.AdminUpdateOrgInput) (*models.Organization, error) { tokenUser := oauth2.ForContext(ctx) if tokenUser == nil { return nil, valid.ErrAuthorization @@ -4198,22 +4203,11 @@ func (r *mutationResolver) UpdateAdminOrgType(ctx context.Context, orgSlug strin WithCode(valid.ErrNotFoundCode) return nil, nil } - _orgType := string(orgType) - if _orgType != models.BillingStatusFree && - _orgType != models.BillingStatusPersonal && - _orgType != models.BillingStatusBusiness && - _orgType != models.BillingStatusOpenSource && - _orgType != models.BillingStatusSponsored { - validator.Error("%s", lt.Translate("Invalid orgType")). - WithField("orgType"). - WithCode(valid.ErrValidationCode) - return nil, nil - } + var hasChanges bool opts := &database.FilterOptions{ Filter: sq.And{ - sq.Eq{"o.slug": orgSlug}, - sq.Eq{"o.is_active": true}, + sq.Eq{"o.slug": input.OrgSlug}, }, Limit: 1, } @@ -4228,10 +4222,41 @@ func (r *mutationResolver) UpdateAdminOrgType(ctx context.Context, orgSlug strin return nil, nil } org := orgs[0] - org.Settings.Billing.Status = _orgType - err = org.Store(ctx) - if err != nil { - return nil, err + + if input.OrgType != nil { + _orgType := string(*input.OrgType) + if _orgType != models.BillingStatusFree && + _orgType != models.BillingStatusPersonal && + _orgType != models.BillingStatusBusiness && + _orgType != models.BillingStatusOpenSource && + _orgType != models.BillingStatusSponsored { + validator.Error("%s", lt.Translate("Invalid orgType")). + WithField("orgType"). + WithCode(valid.ErrValidationCode) + return nil, nil + } + org.Settings.Billing.Status = _orgType + hasChanges = true + } + + if input.Visibility != nil { + vis := string(*input.Visibility) + if vis != models.VisibilityPublic && + vis != models.VisibilityHidden { + validator.Error("%s", lt.Translate("Invalid visibility")). + WithField("visibility"). + WithCode(valid.ErrValidationCode) + return nil, nil + } + org.Visibility = vis + hasChanges = true + } + + if hasChanges { + err = org.Store(ctx) + if err != nil { + return nil, err + } } return org, nil } @@ -4766,6 +4791,11 @@ func (r *organizationResolver) Image(ctx context.Context, obj *models.Organizati panic(fmt.Errorf("not implemented: Image - image")) } +// Visibility is the resolver for the visibility field. +func (r *organizationResolver) Visibility(ctx context.Context, obj *models.Organization) (model.PublicVisibility, error) { + return model.PublicVisibility(obj.Visibility), nil +} + // DefaultPerm is the resolver for the defaultPerm field. func (r *organizationSettingsResolver) DefaultPerm(ctx context.Context, obj *models.OrganizationSettings) (model.LinkVisibility, error) { return model.LinkVisibility(obj.DefaultPerm), nil @@ -4780,7 +4810,7 @@ func (r *qRCodeResolver) CodeType(ctx context.Context, obj *models.QRCode) (mode func (r *queryResolver) Version(ctx context.Context) (*model.Version, error) { return &model.Version{ Major: 0, - Minor: 4, + Minor: 5, Patch: 1, DeprecationDate: nil, }, nil @@ -5308,6 +5338,8 @@ func (r *queryResolver) GetOrgLinks(ctx context.Context, input *model.GetLinkInp linkOpts.Filter = sq.And{ linkOpts.Filter, sq.Eq{"ol.visibility": models.OrgLinkVisibilityPublic}, + sq.Eq{"b.visibility": model.PublicVisibilityPublic}, + sq.Eq{"o.visibility": model.PublicVisibilityPublic}, } } @@ -7046,6 +7078,9 @@ func (r *userResolver) ID(ctx context.Context, obj *models.User) (int, error) { // AuditLog returns AuditLogResolver implementation. func (r *Resolver) AuditLog() AuditLogResolver { return &auditLogResolver{r} } +// BaseURL returns BaseURLResolver implementation. +func (r *Resolver) BaseURL() BaseURLResolver { return &baseURLResolver{r} } + // BillingSettings returns BillingSettingsResolver implementation. func (r *Resolver) BillingSettings() BillingSettingsResolver { return &billingSettingsResolver{r} } @@ -7076,6 +7111,7 @@ func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } func (r *Resolver) User() UserResolver { return &userResolver{r} } type auditLogResolver struct{ *Resolver } +type baseURLResolver struct{ *Resolver } type billingSettingsResolver struct{ *Resolver } type domainResolver struct{ *Resolver } type mutationResolver struct{ *Resolver } diff --git a/api/loaders/loaders.go b/api/loaders/loaders.go index 9b8cde6..ba3ff21 100644 --- a/api/loaders/loaders.go +++ b/api/loaders/loaders.go @@ -3,6 +3,7 @@ package loaders import ( "context" "links" + "links/api/graph/model" "links/models" "strings" "time" @@ -37,6 +38,8 @@ func getPopularLinks(ctx context.Context) func(key []string) ([][]*models.BaseUR // We are preventing blank title links to be public_ready, but just in case sq.NotEq{"b.title": ""}, sq.Eq{"b.public_ready": true}, + sq.Eq{"b.visibility": model.PublicVisibilityPublic}, + sq.Eq{"o.visibility": model.PublicVisibilityPublic}, sq.Gt{"b.counter": 0}, }, OrderBy: "counter DESC, b.id DESC", diff --git a/client.go b/client.go index 62f1733..84836b9 100644 --- a/client.go +++ b/client.go @@ -81,7 +81,7 @@ func Execute(ctx context.Context, op *gqlclient.Operation, result any) error { if ourl.Host == "127.0.0.1" || ourl.Host == "localhost" { ip := IPForContext(ctx) if ip != "" { - trans.AddHeader("X-Real-IP", IPForContext(ctx)) + trans.AddHeader("X-Real-IP", ip) } } } diff --git a/cmd/migrations.go b/cmd/migrations.go index 43f3de1..892605c 100644 --- a/cmd/migrations.go +++ b/cmd/migrations.go @@ -66,5 +66,12 @@ func GetMigrations() []migrate.Migration { 0, links.MigrateFS, ), + migrate.FSFileMigration( + "0007_add_base_org_visibility", + "migrations/0007_add_base_org_visibility.up.sql", + "migrations/0007_add_base_org_visibility.down.sql", + 0, + links.MigrateFS, + ), } } diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go index eac2bcf..d58902e 100644 --- a/internal/translations/catalog.go +++ b/internal/translations/catalog.go @@ -39,87 +39,87 @@ func init() { } var messageKeyToIndex = map[string]int{ - " you can host your own instance if you'd like full control over your own platform.": 407, - "%s": 432, - "%s Links": 522, - "%s: domain not found": 671, - "- LinkTaco Team": 332, - "100%% open source project": 406, - "A link was successfully created.": 482, - "A list was successfully created.": 616, - "A new link was created succesfully": 656, + " you can host your own instance if you'd like full control over your own platform.": 408, + "%s": 433, + "%s Links": 523, + "%s: domain not found": 672, + "- LinkTaco Team": 333, + "100%% open source project": 407, + "A link was successfully created.": 483, + "A list was successfully created.": 617, + "A new link was created succesfully": 657, "A new member invitation was sent to %s": 162, "A new register invitation was sent to %s": 160, - "A new short was created succesfully": 654, - "A new window called Library will open": 555, - "A valid Organizaiton Slug is required.": 247, - "API Powered": 387, - "About": 584, - "Access Restricted": 267, - "Access denied.": 268, + "A new short was created succesfully": 655, + "A new window called Library will open": 556, + "A valid Organizaiton Slug is required.": 248, + "API Powered": 388, + "About": 585, + "Access Restricted": 268, + "Access denied.": 269, "Action": 11, "Actions": 40, - "Add": 300, - "Add Link": 677, - "Add Member": 458, - "Add OAuth2 Client": 302, - "Add Personal Access Token": 289, - "Add unlimited members to organization": 377, - "Admin": 594, - "Admin Write": 463, - "Advanced Search": 498, - "Advanced filtering/search": 354, - "All": 509, + "Add": 301, + "Add Link": 678, + "Add Member": 459, + "Add OAuth2 Client": 303, + "Add Personal Access Token": 290, + "Add unlimited members to organization": 378, + "Admin": 595, + "Admin Write": 464, + "Advanced Search": 499, + "Advanced filtering/search": 355, + "All": 510, "Already have an account? Click here to login": 54, - "An invitation was sent to this user": 464, - "An note was successfully created.": 577, - "An short link was successfully created.": 664, + "An invitation was sent to this user": 465, + "An note was successfully created.": 578, + "An short link was successfully created.": 665, "Analytics": 102, "Apply": 108, - "Approve": 327, - "Archive": 515, - "Archive URL": 481, - "As system admin run this command in the channel you want to connect": 548, + "Approve": 328, + "Archive": 516, + "Archive URL": 482, + "As system admin run this command in the channel you want to connect": 549, "Audit Log": 7, - "Authorize": 322, - "Authorized Clients": 285, + "Authorize": 323, + "Authorized Clients": 286, "Back": 25, - "Back Home": 274, - "BaseURL Not Found": 259, - "Blog": 596, - "Bookmark '%s' on LinkTaco.com": 528, - "Bookmark successfully deleted": 532, - "Bookmarks": 349, - "Browser bookmark widget": 419, - "Build Your Own Integration": 380, - "Business": 341, - "By": 495, + "Back Home": 275, + "BaseURL Not Found": 260, + "Blog": 597, + "Bookmark '%s' on LinkTaco.com": 529, + "Bookmark successfully deleted": 533, + "Bookmarks": 350, + "Browser bookmark widget": 420, + "Build Your Own Integration": 381, + "Business": 342, + "By": 496, "CNAME record for domain is incorrect": 204, "Cancel": 26, - "Categories": 583, + "Categories": 584, "Change Email": 81, "Change Password": 60, "Change password": 41, - "Chrome Bookmarks": 569, + "Chrome Bookmarks": 570, "City": 105, - "City analytics": 374, - "Clear": 501, - "Click analytics": 371, + "City analytics": 375, + "Clear": 502, + "Click analytics": 372, "Click here to upgrade": 112, - "Click on Manage Bookmarks from the Bookmarks menu": 554, - "Click on on Export Bookmarks": 563, - "Click on the icon that has two arrows (up and down) and choose 'Export Bookmarks to HTML'": 557, - "Client Applications": 591, - "Client Description": 303, - "Client ID": 298, - "Client Name": 286, - "Client Secret": 306, - "Client URL": 305, - "Clients": 297, + "Click on Manage Bookmarks from the Bookmarks menu": 555, + "Click on on Export Bookmarks": 564, + "Click on the icon that has two arrows (up and down) and choose 'Export Bookmarks to HTML'": 558, + "Client Applications": 592, + "Client Description": 304, + "Client ID": 299, + "Client Name": 287, + "Client Secret": 307, + "Client URL": 306, + "Clients": 298, "Code is invalid.": 234, - "Collaboration": 413, - "Collaboration / Integrations": 376, - "Comment": 280, + "Collaboration": 414, + "Collaboration / Integrations": 377, + "Comment": 281, "Complete Registration": 47, "Confirm": 98, "Confirm New Password": 63, @@ -128,78 +128,78 @@ var messageKeyToIndex = map[string]int{ "Confirmation Not Found": 168, "Confirmation User Not Found": 187, "Confirmation key is required.": 167, - "Connect": 550, - "Connect Mattermost": 634, - "Connect User": 640, - "Connect to Slack Workspace": 684, - "Connected": 551, + "Connect": 551, + "Connect Mattermost": 635, + "Connect User": 641, + "Connect to Slack Workspace": 685, + "Connected": 552, "Continue to Upgrade": 2, "Country": 104, - "Country analytics": 373, - "Create": 624, - "Create Domain": 427, - "Create Link": 474, - "Create Links": 604, - "Create List": 615, - "Create Note": 576, - "Create Organization": 448, - "Create QR Code": 623, - "Create Short Link": 661, - "Create link listings (ie, social media bios, etc.)": 358, - "Creation Date": 619, + "Country analytics": 374, + "Create": 625, + "Create Domain": 428, + "Create Link": 475, + "Create Links": 605, + "Create List": 616, + "Create Note": 577, + "Create Organization": 449, + "Create QR Code": 624, + "Create Short Link": 662, + "Create link listings (ie, social media bios, etc.)": 359, + "Creation Date": 620, "Current Organization": 37, "Current Password": 61, - "Current password given is incorrect": 691, + "Current password given is incorrect": 692, "CurrentSlug is required": 125, - "Custom background image": 626, - "Custom domain + SSL": 356, + "Custom background image": 627, + "Custom domain + SSL": 357, "Days": 110, - "Default Bookmark Visibility": 450, + "Default Bookmark Visibility": 451, "Default Lang": 20, "Default Language": 35, "DefaultLang is required": 190, - "Delete": 421, - "Delete Bookmark": 530, - "Delete Domain": 431, - "Delete List": 600, - "Delete Org Member": 466, - "Delete Picture": 610, - "Delete QR Code": 541, - "Delete Short Link": 667, - "Delete member %s (%s) from Organization %s?": 469, - "Description": 316, + "Delete": 422, + "Delete Bookmark": 531, + "Delete Domain": 432, + "Delete List": 601, + "Delete Org Member": 467, + "Delete Picture": 611, + "Delete QR Code": 542, + "Delete Short Link": 668, + "Delete member %s (%s) from Organization %s?": 470, + "Description": 317, "Description is required.": 150, "Details": 12, - "Device analytics": 375, + "Device analytics": 376, "Devices": 107, - "Disabled": 441, - "Disconnect": 549, - "Disconnect Mattermost": 631, - "Disconnect Slack": 678, - "Do you really want to disconnect this organization from mattermost": 633, - "Do you really want to disconnect this organization from slack": 680, - "Do you really whant to delete this bookmark?": 533, - "Do you really whant to delete this domain": 435, - "Do you really whant to delete this link": 603, - "Do you really whant to delete this list": 622, - "Do you really whant to delete this qr code": 544, - "Do you want to connect this organization to mattermost?": 636, - "Do you want to connect with slack?": 686, - "Do you want to delete": 535, - "Do you want to proceed?": 642, - "Do you want to revoke this personal access token? This can not be undone.": 292, - "Documentation": 393, - "Domain": 608, - "Domain List": 420, + "Disabled": 442, + "Disconnect": 550, + "Disconnect Mattermost": 632, + "Disconnect Slack": 679, + "Do you really want to disconnect this organization from mattermost": 634, + "Do you really want to disconnect this organization from slack": 681, + "Do you really whant to delete this bookmark?": 534, + "Do you really whant to delete this domain": 436, + "Do you really whant to delete this link": 604, + "Do you really whant to delete this list": 623, + "Do you really whant to delete this qr code": 545, + "Do you want to connect this organization to mattermost?": 637, + "Do you want to connect with slack?": 687, + "Do you want to delete": 536, + "Do you want to proceed?": 643, + "Do you want to revoke this personal access token? This can not be undone.": 293, + "Documentation": 394, + "Domain": 609, + "Domain List": 421, "Domain Not Found": 217, - "Domain created successfully": 430, - "Domain in use. Can not change service.": 250, - "Domain not found": 653, - "Domain successfully deleted": 433, + "Domain created successfully": 431, + "Domain in use. Can not change service.": 251, + "Domain not found": 654, + "Domain successfully deleted": 434, "DomainID is required": 210, - "Domains": 443, - "Download": 625, - "Download Image": 540, + "Domains": 444, + "Download": 626, + "Download Image": 541, "Duplicated short code": 218, "Edit": 38, "Edit Profile": 18, @@ -209,395 +209,396 @@ var messageKeyToIndex = map[string]int{ "Email": 34, "Email Address": 52, "Email is required": 175, - "Email is required.": 252, + "Email is required.": 253, "Email may not exceed 255 characters": 155, "Email updated successfully": 87, - "Enabled": 440, + "Enabled": 441, "Engagements over time": 103, "English": 28, "Enter New Password": 64, "Error checking the DNS entry for domain. Please try again later": 203, "Error compiling url regex: %s": 152, - "Error fetching referenced link: %v": 484, - "Error fetching referenced note: %v": 578, - "Error fetching referenced url: Not found": 483, - "Every account can create unlimited organizations. Each organization has it's own bookmarks, listings, analytics, etc. All of the features below belong to each organization with their own unique URL's, groupings, and so on.": 337, - "Exclude Tags": 500, - "Expired": 282, - "Explore Features": 410, - "Export": 445, - "Export Data": 545, - "Export in JSON or HTML": 386, - "Failed the '%s' tag.": 695, - "Feature": 338, - "Feed": 494, - "File format": 546, - "Filter/Search listings": 360, - "Filter/Search shorts": 367, - "Firefox Bookmarks": 570, - "Follow": 516, - "Follow other organizations (social)": 352, - "Following": 491, - "Followings": 502, + "Error fetching referenced link: %v": 485, + "Error fetching referenced note: %v": 579, + "Error fetching referenced url: Not found": 484, + "Every account can create unlimited organizations. Each organization has it's own bookmarks, listings, analytics, etc. All of the features below belong to each organization with their own unique URL's, groupings, and so on.": 338, + "Exclude Tags": 501, + "Expired": 283, + "Explore Features": 411, + "Export": 446, + "Export Data": 546, + "Export in JSON or HTML": 387, + "Failed the '%s' tag.": 696, + "Feature": 339, + "Feed": 495, + "File format": 547, + "Filter/Search listings": 361, + "Filter/Search shorts": 368, + "Firefox Bookmarks": 571, + "Follow": 517, + "Follow other organizations (social)": 353, + "Following": 492, + "Followings": 503, "Forgot Password?": 71, - "Free": 339, + "Free": 340, "Free accounts are only allowed 1 link listing.": 222, "Free organizations are not allowed to create private links. Please upgrade": 144, "Free organizations are not allowed to create private notes. Please upgrade": 151, "Free organizations can not use Private permission. Please upgrade to use Private permission": 134, - "Full Analytics": 362, - "Full GraphQL API Access": 388, + "Full Analytics": 363, + "Full GraphQL API Access": 389, "Full Name": 48, - "Full RSS feeds": 355, - "Full analytics history": 369, - "Fully open source": 391, - "GQL Playground": 587, - "Go to https://pinboard.in/export/ and click on JSON": 564, - "Go to the Bookmarks menu and choose Bookmark Manager": 560, - "Go to the File menu and chose Export": 558, - "Grants": 287, - "GraphQL Playground": 272, - "Help": 595, - "Here you can mix all your link saving and sharing needs in one tight little bundle. Much like a taco. A link taco if you will.": 397, - "Hi there,": 330, - "Host your own version of Link Taco": 392, + "Full RSS feeds": 356, + "Full analytics history": 370, + "Fully open source": 392, + "GQL Playground": 588, + "Go to https://pinboard.in/export/ and click on JSON": 565, + "Go to the Bookmarks menu and choose Bookmark Manager": 561, + "Go to the File menu and chose Export": 559, + "Grants": 288, + "GraphQL Playground": 273, + "Help": 596, + "Here you can mix all your link saving and sharing needs in one tight little bundle. Much like a taco. A link taco if you will.": 398, + "Hi there,": 331, + "Host your own version of Link Taco": 393, "ID can't be lower than 0.": 231, "ID is required.": 229, "IP Address": 8, "Id required": 219, - "If OAuth 2.0 bearer tokens issued for your OAuth client, or your client secret, have been disclosed to a third-party, you must revoke all tokens and have replacements issued.": 310, + "If OAuth 2.0 bearer tokens issued for your OAuth client, or your client secret, have been disclosed to a third-party, you must revoke all tokens and have replacements issued.": 311, "If the email address given exists in our system then we just sent it a login link. Click this link to reset your password. The link expires in 1 hour.": 72, "If you didn't request this link you can safely delete this email now.": 99, "Image": 24, - "Import": 446, - "Import / Export": 381, - "Import Data": 552, - "Import Export": 415, - "Import from Chrome": 384, - "Import from Firefox": 383, - "Import from Pinboard": 382, - "Import from Safari": 385, - "In order to interact with Link Taco you have to connect you slack account with your link user": 682, - "In order to interact with the mattermost you have to connect your account with your link user": 641, - "In the left sidebar select the folder that you want to export": 561, - "In the left sidebar select the folder you want to export. To export all bookmarks select All Bookmarks": 556, - "In the top bookmark bar click on the three points at the top right": 562, - "Inactive Domain": 333, - "Include Tags": 499, - "Informative URL": 317, - "Installed successfully": 658, - "Instructions": 567, - "Integrations": 414, + "Import": 447, + "Import / Export": 382, + "Import Data": 553, + "Import Export": 416, + "Import from Chrome": 385, + "Import from Firefox": 384, + "Import from Pinboard": 383, + "Import from Safari": 386, + "In order to interact with Link Taco you have to connect you slack account with your link user": 683, + "In order to interact with the mattermost you have to connect your account with your link user": 642, + "In the left sidebar select the folder that you want to export": 562, + "In the left sidebar select the folder you want to export. To export all bookmarks select All Bookmarks": 557, + "In the top bookmark bar click on the three points at the top right": 563, + "Inactive Domain": 334, + "Include Tags": 500, + "Informative URL": 318, + "Installed successfully": 659, + "Instructions": 568, + "Integrations": 415, "Invalid Confirmation Target": 170, "Invalid Confirmation Type": 169, "Invalid Email": 182, "Invalid FQDN format": 197, - "Invalid ID ": 249, + "Invalid ID ": 250, "Invalid Key": 181, "Invalid Permission": 157, "Invalid URL.": 137, "Invalid Visibility value.": 136, - "Invalid code type": 265, + "Invalid code type": 266, "Invalid default permission value": 135, "Invalid domain ID.": 205, "Invalid domain name.": 193, - "Invalid email and/or password": 688, + "Invalid email and/or password": 689, "Invalid email format": 156, - "Invalid level value.": 245, - "Invalid listing ID provided": 270, - "Invalid listing for specified organization": 271, + "Invalid level value.": 246, + "Invalid listing ID provided": 271, + "Invalid listing for specified organization": 272, "Invalid orgType": 244, - "Invalid origin source for importer.": 275, + "Invalid origin source for importer.": 276, "Invalid permissions for Organization ID": 199, "Invalid service value.": 194, - "Invalid slack response": 685, - "Invalid status value.": 246, - "Invalid tag cloud type without organization slug": 260, + "Invalid slack response": 686, + "Invalid status value.": 247, + "Invalid tag cloud type without organization slug": 261, + "Invalid visibility": 245, "Is Active": 33, - "Is Default": 609, - "Is Enabled": 456, - "Issued": 281, - "Just wanted to let you know that your bookmark import has completed successfully!": 331, + "Is Default": 610, + "Is Enabled": 457, + "Issued": 282, + "Just wanted to let you know that your bookmark import has completed successfully!": 332, "Key is required": 186, "Lang is invalid": 191, - "Link Detail": 525, + "Link Detail": 526, "Link Listing": 10, - "Link Listings": 357, - "Link Lists": 412, + "Link Listings": 358, + "Link Lists": 413, "Link Not Found": 148, - "Link Search": 674, - "Link Short Not Found": 264, - "Link Shortening": 364, - "Link Shortner": 425, + "Link Search": 675, + "Link Short Not Found": 265, + "Link Shortening": 365, + "Link Shortner": 426, "Link Taco: Invitation to join organization": 163, "Link hash required": 145, - "Link listings: Linktree et al": 403, - "Link shortening: Bitly et al": 402, - "Link successfully deleted": 602, - "Link successfully updated.": 536, + "Link listings: Linktree et al": 404, + "Link shortening: Bitly et al": 403, + "Link successfully deleted": 603, + "Link successfully updated.": 537, "LinkOrder can't be lower than 0.": 227, "LinkTaco - Confirm account email": 95, - "LinkTaco - Your bookmark import is complete": 329, - "LinkTaco is an open source platform where you can host all of your links. Custom domains, QR codes, Analytics, full API, multiple organizations w/unlimited members are just some of what's included.": 398, + "LinkTaco - Your bookmark import is complete": 330, + "LinkTaco is an open source platform where you can host all of your links. Custom domains, QR codes, Analytics, full API, multiple organizations w/unlimited members are just some of what's included.": 399, "Links": 116, "Links - Reset your password": 70, - "Linktaco: Invitation to Register": 254, + "Linktaco: Invitation to Register": 255, "List Not Found": 236, - "List successfully deleted": 621, - "Listing": 363, + "List successfully deleted": 622, + "Listing": 364, "Listing Link Not Found": 232, "Listing Not Found": 228, - "Listing successfully updated.": 614, + "Listing successfully updated.": 615, "ListingSlug is required.": 226, - "Lists": 592, - "Log in": 585, - "Log out": 586, + "Lists": 593, + "Log in": 586, + "Log out": 587, "Login": 82, "Login Email": 84, - "Lookup Name": 422, - "Manage": 299, - "Manage Links": 617, - "Manage Members": 444, - "Manage Subscription": 442, + "Lookup Name": 423, + "Manage": 300, + "Manage Links": 618, + "Manage Members": 445, + "Manage Subscription": 443, "Manage Your Organizations": 44, - "Mark as read": 511, - "Mark as unread": 512, - "MatterMost Integration": 379, - "Mattermost successfully disconnected": 632, - "Member List": 472, - "Member added succesxfully": 470, - "Member successfully deleted": 468, + "Mark as read": 512, + "Mark as unread": 513, + "MatterMost Integration": 380, + "Mattermost successfully disconnected": 633, + "Member List": 473, + "Member added succesxfully": 471, + "Member successfully deleted": 469, "Members": 39, - "Members can add/edit/remove links (if allowed)": 417, - "Members have access based on permissions granted": 418, - "Migrate Short Links": 428, - "Most popular links on LinkTaco.com": 488, + "Members can add/edit/remove links (if allowed)": 418, + "Members have access based on permissions granted": 419, + "Migrate Short Links": 429, + "Most popular links on LinkTaco.com": 489, "Name": 22, "Name is required": 118, - "Name is required.": 251, + "Name is required.": 252, "Name may not exceed 150 characters": 119, "Name may not exceed 255 characters": 195, "Name may not exceed 500 characters": 196, "New Password": 62, - "New passwords do not match": 689, + "New passwords do not match": 690, "Next": 15, - "No Clients": 301, + "No Clients": 302, "No Data": 117, - "No Domain": 663, - "No Domains": 426, - "No Links": 606, - "No Lists": 618, - "No QR Codes": 630, - "No Short Links": 660, - "No URL argument was given": 670, + "No Domain": 664, + "No Domains": 427, + "No Links": 607, + "No Lists": 619, + "No QR Codes": 631, + "No Short Links": 661, + "No URL argument was given": 671, "No accounts? Click here to create one": 83, "No audit logs to display": 14, - "No links were found for %s": 647, - "No members": 473, - "No organization found": 648, - "No organizations": 493, + "No links were found for %s": 648, + "No members": 474, + "No organization found": 649, + "No organizations": 494, "No personal organization found for this user": 192, - "No slack connection found": 644, - "No, nevermind": 294, - "Not Found": 258, - "Note": 573, - "Note '%s' on LinkTaco.com": 574, - "Note: Your access token will never be shown to you again. Keep this secret. It will expire a year from now.": 290, - "Note: Your client secret will never be shown to you again.": 307, - "OAuth 2.0 client management": 308, - "OAuth 2.0 client registered": 318, - "OAuth2 Support": 389, - "Old links won't work. All code will be moved to the new domain.": 429, - "Only members with read perm are allowed to perform this action": 261, + "No slack connection found": 645, + "No, nevermind": 295, + "Not Found": 259, + "Note": 574, + "Note '%s' on LinkTaco.com": 575, + "Note: Your access token will never be shown to you again. Keep this secret. It will expire a year from now.": 291, + "Note: Your client secret will never be shown to you again.": 308, + "OAuth 2.0 client management": 309, + "OAuth 2.0 client registered": 319, + "OAuth2 Support": 390, + "Old links won't work. All code will be moved to the new domain.": 430, + "Only members with read perm are allowed to perform this action": 262, "Only members with write perm are allowed to perform this action": 143, "Only showing country data. Upgrade your organization to paid to view all stats": 113, "Only showing the last 60 days. Upgrade your organization to paid to view all historical data": 111, "Only superusers can delete system level domains": 207, - "Only superusers can fetch system level domains": 263, - "Open Source": 437, - "Order": 599, + "Only superusers can fetch system level domains": 264, + "Open Source": 438, + "Order": 600, "Org Not Found": 214, "Org Slug is required": 221, - "Org Username": 449, + "Org Username": 450, "Org slug is required": 153, - "Org slug is required for this kind of token": 266, + "Org slug is required for this kind of token": 267, "Org slug is required.": 139, "Org username is required": 120, "Org username may not exceed 150 characters": 121, "Organizaiton Slug is required.": 198, "Organization": 9, "Organization Not Found": 128, - "Organization Slug is required for user level domains": 248, - "Organization created successfully": 454, - "Organization linked successfully with mattermost": 638, - "Organization linked successfully with slack": 687, - "Organization not found.": 269, - "Organization updated successfully": 457, + "Organization Slug is required for user level domains": 249, + "Organization created successfully": 455, + "Organization linked successfully with mattermost": 639, + "Organization linked successfully with slack": 688, + "Organization not found.": 270, + "Organization updated successfully": 458, "Organizations": 36, - "Organize Bookmarks": 411, - "Organize by tags": 353, - "Organize listings by tag": 359, - "Organize shorts by tags": 366, - "Other": 611, - "Other Name": 612, - "Paid": 439, + "Organize Bookmarks": 412, + "Organize by tags": 354, + "Organize listings by tag": 360, + "Organize shorts by tags": 367, + "Other": 612, + "Other Name": 613, + "Paid": 440, "Password": 49, "Password Changed": 66, "Password changed successfully": 86, "Password is required": 176, "Password may not exceed 100 characters": 177, - "Payment History": 447, - "Peace Pinboard. Bye Bitly. Later Linktree. Hello LinkTaco!": 404, - "Permission": 459, + "Payment History": 448, + "Peace Pinboard. Bye Bitly. Later Linktree. Hello LinkTaco!": 405, + "Permission": 460, "Permission Not Found": 171, - "Personal": 340, - "Personal Access Tokens": 279, - "Personal Tokens": 590, - "Please click in the following link to tie a org %s": 657, - "Please click the link below:": 256, + "Personal": 341, + "Personal Access Tokens": 280, + "Personal Tokens": 591, + "Please click in the following link to tie a org %s": 658, + "Please click the link below:": 257, "Please confirm your account": 96, - "Please enter a valid email address.": 693, - "Please enter a valid phone number.": 694, - "Please link your slack user with link: %s": 675, + "Please enter a valid email address.": 694, + "Please enter a valid phone number.": 695, + "Please link your slack user with link: %s": 676, "Please login to view multiple tag combos (sorry, this is to help stop bot abuse)": 6, - "Please upgrade to a Business organization to add members": 460, - "Please upgrade your account to reactivate it": 335, - "Popular": 582, - "Popular Bookmarks": 486, - "Popular Links": 490, + "Please upgrade to a Business organization to add members": 461, + "Please upgrade your account to reactivate it": 336, + "Popular": 583, + "Popular Bookmarks": 487, + "Popular Links": 491, "Prev": 16, - "Previous": 605, - "Price": 342, - "Pricing": 336, - "Pricing and feature details for LinkTaco.com": 394, - "Private": 453, - "Private Post": 527, + "Previous": 606, + "Price": 343, + "Pricing": 337, + "Pricing and feature details for LinkTaco.com": 395, + "Private": 454, + "Private Post": 528, "Profile updated successfully": 29, - "Public": 452, - "Public Post": 526, - "Public only": 347, - "QR Code Details": 539, - "QR Code Listing": 628, + "Public": 453, + "Public Post": 527, + "Public only": 348, + "QR Code Details": 540, + "QR Code Listing": 629, "QR Code Not Found": 240, - "QR Code specific analytics": 370, - "QR Code succesfully created": 627, - "QR Code successfully deleted": 543, - "QR Codes": 620, - "QR Codes powered by Link Taco!": 537, + "QR Code specific analytics": 371, + "QR Code succesfully created": 628, + "QR Code successfully deleted": 544, + "QR Codes": 621, + "QR Codes powered by Link Taco!": 538, "QR Scans": 115, - "Read": 461, - "Ready to get started? It's free to make an account and use it forever (with some limitations). To use all features you have to pay just a few bucks a year, or a few per month if you're a business, and that's it. Simple!": 409, - "Recent": 581, - "Recent Bookmarks": 508, - "Recent Links": 521, - "Recent bookmarks for URL %s added on LinkTaco.com": 505, - "Recent public links added to %s on LinkTaco.com": 519, - "Recent public links added to LinkTaco.com": 520, - "Redirect URL": 304, - "Referer analyitcs": 372, + "Read": 462, + "Ready to get started? It's free to make an account and use it forever (with some limitations). To use all features you have to pay just a few bucks a year, or a few per month if you're a business, and that's it. Simple!": 410, + "Recent": 582, + "Recent Bookmarks": 509, + "Recent Links": 522, + "Recent bookmarks for URL %s added on LinkTaco.com": 506, + "Recent public links added to %s on LinkTaco.com": 520, + "Recent public links added to LinkTaco.com": 521, + "Redirect URL": 305, + "Referer analyitcs": 373, "Referrer": 106, "Register": 51, - "Register Invitation": 253, + "Register Invitation": 254, "Registration Completed": 50, "Registration is not enabled": 180, "Registration is not enabled on this system. Contact the admin for an account.": 57, - "Reject": 328, + "Reject": 329, "Reset Password": 65, "Restricted Page": 0, - "Revoke": 283, - "Revoke Personal Access Token": 291, - "Revoke client tokens": 311, - "Revoke tokens & client secret": 309, - "Safari Bookmarks": 568, + "Revoke": 284, + "Revoke Personal Access Token": 292, + "Revoke client tokens": 312, + "Revoke tokens & client secret": 310, + "Safari Bookmarks": 569, "Save": 19, - "Save Link": 588, - "Save Note": 589, - "Save public/private links": 350, - "Save public/private notes": 351, - "Saved Bookmarks": 503, - "Scopes": 326, - "Search": 496, - "See the installation documentation for more.": 408, - "Select Export Bookmarks": 559, - "Self Hosting": 390, + "Save Link": 589, + "Save Note": 590, + "Save public/private links": 351, + "Save public/private notes": 352, + "Saved Bookmarks": 504, + "Scopes": 327, + "Search": 497, + "See the installation documentation for more.": 409, + "Select Export Bookmarks": 560, + "Self Hosting": 391, "Send Reset Link": 73, - "Service": 423, + "Service": 424, "Set up your account, so you can save links.": 56, "Settings": 30, - "Short Code": 662, + "Short Code": 663, "Short Code may not exceed 20 characters": 212, - "Short Link": 659, - "Short Link successfully deleted": 668, - "Short Links": 593, + "Short Link": 660, + "Short Link successfully deleted": 669, + "Short Links": 594, "Short Not Found": 238, - "Short link successfully updated.": 666, - "Since we're a": 405, - "Slack Integration": 378, - "Slack successfully disconnected": 679, + "Short link successfully updated.": 667, + "Since we're a": 406, + "Slack Integration": 379, + "Slack successfully disconnected": 680, "Slug": 31, "Slug is required": 126, "Slug is required.": 220, "Slug may not exceed 150 characters": 127, - "Social Links": 613, - "Social bookmarking is not new, it's just been forgotten. Link shortening with analytics has been around forever. Link listings became cool once social media started allowing us to post a link to our websites in our profiles.": 399, + "Social Links": 614, + "Social bookmarking is not new, it's just been forgotten. Link shortening with analytics has been around forever. Link listings became cool once social media started allowing us to post a link to our websites in our profiles.": 400, "Social bookmarking plus link sharing, shortening and listings all in one app.": 3, - "Social bookmarking: Pinboard (Delicious)": 401, + "Social bookmarking: Pinboard (Delicious)": 402, "Someone, possibly you, requested this login via email link. To login to your account, just click the link below:": 85, "Someone, possibly you, requested to reset your Links email address. To complete this update, just click the link below:": 79, "Someone, possibly you, requested to reset your Links password.": 74, - "Something went wrong, impossible to send invitation": 465, - "Something went wrong. Impossible to get the member data": 471, - "Something went wrong. The QR Code could not be deleted.": 542, - "Something went wrong. The link could not be deleted.": 601, - "Something went wrong. The user could not be linked.": 683, - "Something went wrong. This bookmark could not be deleted.": 531, - "Something went wrong. This member could not be deleted: %s": 467, - "Sorry, free accounts do not support Mattermost Integration. Please upgrade to continue": 639, - "Sorry, free accounts do not support Slack Integration. Please upgrade to continue": 681, - "Sorry, you have exceeded the amount of free accounts available. Please update your current free account to create one more": 451, - "Source": 553, + "Something went wrong, impossible to send invitation": 466, + "Something went wrong. Impossible to get the member data": 472, + "Something went wrong. The QR Code could not be deleted.": 543, + "Something went wrong. The link could not be deleted.": 602, + "Something went wrong. The user could not be linked.": 684, + "Something went wrong. This bookmark could not be deleted.": 532, + "Something went wrong. This member could not be deleted: %s": 468, + "Sorry, free accounts do not support Mattermost Integration. Please upgrade to continue": 640, + "Sorry, free accounts do not support Slack Integration. Please upgrade to continue": 682, + "Sorry, you have exceeded the amount of free accounts available. Please update your current free account to create one more": 452, + "Source": 554, "Spanish": 27, - "Sponsored": 438, - "Star": 513, - "Starred": 478, - "Store Dashboard": 579, - "Submit Query": 273, + "Sponsored": 439, + "Star": 514, + "Starred": 479, + "Store Dashboard": 580, + "Submit Query": 274, "Subscription": 32, "Successful login.": 94, - "Successfully added client": 319, - "Successfully added personal access": 295, - "Successfully reissued client.": 321, - "Successfully revoked authorization token.": 296, - "Successfully revoked client.": 320, - "Tags": 479, + "Successfully added client": 320, + "Successfully added personal access": 296, + "Successfully reissued client.": 322, + "Successfully revoked authorization token.": 297, + "Successfully revoked client.": 321, + "Tags": 480, "Tags may not exceed 10": 142, - "The %s domain is currently inactive": 334, + "The %s domain is currently inactive": 335, "The User is not verified": 173, "The User you try to invite is not verified": 161, - "The code is required": 651, + "The code is required": 652, "The domain is already registered in the system": 201, - "The domain is required": 652, - "The file is required": 276, - "The file submitted for this source should be html": 277, - "The file submitted for this source should be json": 278, + "The domain is required": 653, + "The file is required": 277, + "The file submitted for this source should be html": 278, + "The file submitted for this source should be json": 279, "The member was removed successfully": 166, "The passwords you entered do not match.": 17, - "The text to be searched is required": 646, - "The title is required": 649, - "The url is required": 650, + "The text to be searched is required": 647, + "The title is required": 650, + "The url is required": 651, "The user for given email is not a member of given organization": 165, "The user was added successfully": 174, "There is already a default listing for this domain": 225, "There is already a domain registered for given service": 202, "This Slug is already registered for this domain": 224, "This account is currently unable to access the system.": 93, - "This ain't a popularity contest or anything but this is weird that there are no links!": 487, + "This ain't a popularity contest or anything but this is weird that there are no links!": 488, "This email domain is not allowed": 158, "This email is already registered": 183, - "This feature is not allowed for free user. Please upgrade.": 547, - "This feature is restricted to free accounts. Please upgrade.": 637, - "This feed has no links. Booo!": 504, - "This field is required.": 692, + "This feature is not allowed for free user. Please upgrade.": 548, + "This feature is restricted to free accounts. Please upgrade.": 638, + "This feed has no links. Booo!": 505, + "This field is required.": 693, "This function is only allowed for business users.": 159, "This function is only allowed for paid users.": 200, "This function is only allowed for paid users. Please upgrade": 1, @@ -609,17 +610,17 @@ var messageKeyToIndex = map[string]int{ "This organization slug is already registered": 124, "This shortCode can not be used. Please chose another one": 213, "This slug can not be used. Please chose another one": 130, - "This team is already tied to an organization": 635, + "This team is already tied to an organization": 636, "This user does not follow this org": 242, "This user is not allowed to perform this action": 149, "This username can not be used. Please chose another one": 184, "This username is already registered": 185, - "This will permanently unregister your OAuth 2.0 client": 313, + "This will permanently unregister your OAuth 2.0 client": 314, "Timestamp": 13, "Timezone": 21, "Timezone is invalid": 189, "Timezone is required": 188, - "Title": 475, + "Title": 476, "Title is required": 230, "Title is required.": 140, "Title is too long.": 233, @@ -627,117 +628,117 @@ var messageKeyToIndex = map[string]int{ "Title may not exceed 500 characters": 141, "To complete your password reset, just click the link below:": 75, "To confirm your email address and complete your Links registration, please click the link below.": 97, - "Tour": 580, - "Try It FREE": 348, - "URL": 598, - "URL Shortening powered by Link Taco!": 669, + "Tour": 581, + "Try It FREE": 349, + "URL": 599, + "URL Shortening powered by Link Taco!": 670, "URL is required.": 209, "URL may not exceed 2048 characters": 138, "Unable to delete. Domain has active short links or link listings": 208, - "Unable to find suitable organization": 262, - "Unfollow": 492, - "Unlimited": 346, - "Unlimited QR codes per listing": 361, - "Unlimited QR codes per short": 368, - "Unlimited link listings (for social media bios, etc.)": 416, - "Unlimited short links": 365, - "Unread": 477, - "Unregister": 315, - "Unregister this OAuth client": 312, - "Unstar": 514, - "Untagged": 510, - "Up until now, all of these things were hosted on different services.": 400, + "Unable to find suitable organization": 263, + "Unfollow": 493, + "Unlimited": 347, + "Unlimited QR codes per listing": 362, + "Unlimited QR codes per short": 369, + "Unlimited link listings (for social media bios, etc.)": 417, + "Unlimited short links": 366, + "Unread": 478, + "Unregister": 316, + "Unregister this OAuth client": 313, + "Unstar": 515, + "Untagged": 511, + "Up until now, all of these things were hosted on different services.": 401, "Update Email": 77, - "Update Link": 534, - "Update Links": 597, - "Update List": 607, - "Update Note": 572, - "Update Organization": 455, - "Update Short Link": 665, + "Update Link": 535, + "Update Links": 598, + "Update List": 608, + "Update Note": 573, + "Update Organization": 456, + "Update Short Link": 666, "Update email": 42, "Upgrade Org": 45, - "Upgrade the organization to activate them.": 524, - "Upgrade your account to support private bookmarks.": 566, + "Upgrade the organization to activate them.": 525, + "Upgrade your account to support private bookmarks.": 567, "Upgrade your organization to paid to view the detail stats": 114, - "Url is required": 655, - "Use commas to separate your tags. Example: tag 1, tag 2, tag 3": 480, + "Url is required": 656, + "Use commas to separate your tags. Example: tag 1, tag 2, tag 3": 481, "User Not Found": 172, - "User connected successfully": 643, + "User connected successfully": 644, "User email is required": 154, "User follows %s": 241, - "User is not authenticated": 690, + "User is not authenticated": 691, "User not found for given email": 164, "User unfollows %s": 243, "Username": 23, "Username is required": 178, "Username may not exceed 150 characters": 179, - "View": 629, + "View": 630, "View Audit Logs": 46, - "Visibility": 476, + "Visibility": 477, "We sent you a confirmation email. Please click the link in that email to confirm your account.": 58, - "We sent you a direct message with instructions": 676, + "We sent you a direct message with instructions": 677, "We sent you a new confirmation email. Please click the link in that email to confirm your account.": 101, - "We sent you a private msg": 645, + "We sent you a private msg": 646, "Weeks": 109, - "Welcome to LinkTaco!": 396, + "Welcome to LinkTaco!": 397, "Welcome to LinkTaco! Here you can mix all your link saving and sharing needs in one tight little bundle. Much like a taco. A link taco if you will.": 4, "Welcome to Links": 55, - "Write": 462, - "Yes": 434, - "Yes, do it": 293, + "Write": 463, + "Yes": 435, + "Yes, do it": 294, "You are not allowed to create more free organizations. Please upgrade to a paid org": 122, "You are not allowed to edit this field for notes": 147, "You are not allowed to enable/disabled user type organization": 131, "You are not allowed to have more than two free organizations. Please upgrade": 132, - "You can not send both after and before cursors": 257, + "You can not send both after and before cursors": 258, "You can now": 67, "You can't create more than 5 qr codes per lists.": 237, "You can't create more than 5 qr codes per shorts.": 239, - "You have %d restricted link(s) saved.": 523, - "You have been invited by %s to join Link Taco": 255, - "You have not created any personal access tokens for your account.": 284, - "You have not granted any third party clients access to your account.": 288, + "You have %d restricted link(s) saved.": 524, + "You have been invited by %s to join Link Taco": 256, + "You have not created any personal access tokens for your account.": 285, + "You have not granted any third party clients access to your account.": 289, "You have reached your monthly short link limit. Please upgrade to remove this limitation.": 215, "You have successfully registered your account. You can now login.": 59, - "You may revoke this access at any time on the OAuth tab of your account profile.": 325, + "You may revoke this access at any time on the OAuth tab of your account profile.": 326, "You must verify your email address before logging in": 92, - "You will be redirected in 10 seconds.": 538, + "You will be redirected in 10 seconds.": 539, "You've been logged out successfully.": 88, "You've been sent a confirmation email. Please click the link in the email to confirm your email change. The confirmation email will expire in 2 hours.": 78, "You've successfully confirmed your email address.": 91, "You've successfully updated your email address.": 90, "You've successfully updated your password.": 89, - "Your Organizations": 436, - "Your bookmark import is being processed. We will notify you once it's complete.": 571, - "Your feed is empty :( Go follow some people. Try the Popular or Recent feeds to find some interesting people to follow.": 497, - "Your importing into a free account / organization, any private pinboard bookmarks will be marked restricted.": 565, - "Your link was successfully saved. Details here: %s": 673, - "Your short link was successfully created: %s": 672, + "Your Organizations": 437, + "Your bookmark import is being processed. We will notify you once it's complete.": 572, + "Your feed is empty :( Go follow some people. Try the Popular or Recent feeds to find some interesting people to follow.": 498, + "Your importing into a free account / organization, any private pinboard bookmarks will be marked restricted.": 566, + "Your link was successfully saved. Details here: %s": 674, + "Your short link was successfully created: %s": 673, "and login": 69, - "bookmark": 485, - "bookmark, note, detail, popular, links, linktaco": 529, - "for": 424, + "bookmark": 486, + "bookmark, note, detail, popular, links, linktaco": 530, + "for": 425, "invalid domain ID": 206, - "is a third-party application operated by": 324, + "is a third-party application operated by": 325, "list-service-domain is not configured": 223, - "months": 345, - "newest": 517, - "note, detail, popular, links, linktaco": 575, - "oldest": 518, - "per month": 344, - "per year": 343, - "popular, links, linktaco, feature, plans, pricing plans": 489, - "pricing, links, linktaco, feature, plans, pricing plans": 395, - "recent, public, links, linktaco": 506, + "months": 346, + "newest": 518, + "note, detail, popular, links, linktaco": 576, + "oldest": 519, + "per month": 345, + "per year": 344, + "popular, links, linktaco, feature, plans, pricing plans": 490, + "pricing, links, linktaco, feature, plans, pricing plans": 396, + "recent, public, links, linktaco": 507, "return to the login page": 68, - "revoke all tokens issued to it, and prohibit the issuance of new tokens.": 314, - "saved": 507, + "revoke all tokens issued to it, and prohibit the issuance of new tokens.": 315, + "saved": 508, "short-service-domain is not configured": 216, "social bookmarks, bookmarking, links, link sharing, link shortening, link listings, bookmarks, link saving, qr codes, analytics": 5, - "would like to access to your Link Taco account.": 323, + "would like to access to your Link Taco account.": 324, } -var enIndex = []uint32{ // 697 elements +var enIndex = []uint32{ // 698 elements // Entry 0 - 1F 0x00000000, 0x00000010, 0x0000004d, 0x00000061, 0x000000af, 0x00000143, 0x000001c3, 0x00000214, @@ -807,137 +808,137 @@ var enIndex = []uint32{ // 697 elements 0x00001df2, 0x00001e09, 0x00001e1c, 0x00001e2d, 0x00001e44, 0x00001e53, 0x00001e84, 0x00001e94, 0x00001ec6, 0x00001ed8, 0x00001eeb, 0x00001f0e, - 0x00001f23, 0x00001f33, 0x00001f48, 0x00001f5e, - 0x00001f85, 0x00001fba, 0x00001fca, 0x00001ff1, - 0x00002003, 0x00002016, 0x0000202a, 0x0000204b, + 0x00001f23, 0x00001f33, 0x00001f46, 0x00001f5b, + 0x00001f71, 0x00001f98, 0x00001fcd, 0x00001fdd, + 0x00002004, 0x00002016, 0x00002029, 0x0000203d, // Entry 100 - 11F - 0x0000207c, 0x00002099, 0x000020c8, 0x000020d2, - 0x000020e4, 0x00002115, 0x00002154, 0x00002179, - 0x000021a8, 0x000021bd, 0x000021cf, 0x000021fb, - 0x0000220d, 0x0000221c, 0x00002234, 0x00002250, - 0x0000227b, 0x0000228e, 0x0000229b, 0x000022a5, - 0x000022c9, 0x000022de, 0x00002310, 0x00002342, - 0x00002359, 0x00002361, 0x00002368, 0x00002370, - 0x00002377, 0x000023b9, 0x000023cc, 0x000023d8, + 0x0000205e, 0x0000208f, 0x000020ac, 0x000020db, + 0x000020e5, 0x000020f7, 0x00002128, 0x00002167, + 0x0000218c, 0x000021bb, 0x000021d0, 0x000021e2, + 0x0000220e, 0x00002220, 0x0000222f, 0x00002247, + 0x00002263, 0x0000228e, 0x000022a1, 0x000022ae, + 0x000022b8, 0x000022dc, 0x000022f1, 0x00002323, + 0x00002355, 0x0000236c, 0x00002374, 0x0000237b, + 0x00002383, 0x0000238a, 0x000023cc, 0x000023df, // Entry 120 - 13F - 0x000023df, 0x00002424, 0x0000243e, 0x000024bb, - 0x000024d8, 0x00002522, 0x0000252d, 0x0000253b, - 0x0000255e, 0x00002588, 0x00002590, 0x0000259a, - 0x000025a1, 0x000025a5, 0x000025b0, 0x000025c2, - 0x000025d5, 0x000025e2, 0x000025ed, 0x000025fb, - 0x00002636, 0x00002652, 0x00002670, 0x0000271f, - 0x00002734, 0x00002751, 0x00002788, 0x000027d1, - 0x000027dc, 0x000027e8, 0x000027f8, 0x00002814, + 0x000023eb, 0x000023f2, 0x00002437, 0x00002451, + 0x000024ce, 0x000024eb, 0x00002535, 0x00002540, + 0x0000254e, 0x00002571, 0x0000259b, 0x000025a3, + 0x000025ad, 0x000025b4, 0x000025b8, 0x000025c3, + 0x000025d5, 0x000025e8, 0x000025f5, 0x00002600, + 0x0000260e, 0x00002649, 0x00002665, 0x00002683, + 0x00002732, 0x00002747, 0x00002764, 0x0000279b, + 0x000027e4, 0x000027ef, 0x000027fb, 0x0000280b, // Entry 140 - 15F - 0x0000282e, 0x0000284b, 0x00002869, 0x00002873, - 0x000028a3, 0x000028cc, 0x0000291d, 0x00002924, - 0x0000292c, 0x00002933, 0x0000295f, 0x00002969, - 0x000029bb, 0x000029cb, 0x000029db, 0x00002a02, - 0x00002a2f, 0x00002a37, 0x00002b16, 0x00002b1e, - 0x00002b23, 0x00002b2c, 0x00002b35, 0x00002b3b, - 0x00002b44, 0x00002b4e, 0x00002b55, 0x00002b5f, - 0x00002b6b, 0x00002b77, 0x00002b81, 0x00002b9b, + 0x00002827, 0x00002841, 0x0000285e, 0x0000287c, + 0x00002886, 0x000028b6, 0x000028df, 0x00002930, + 0x00002937, 0x0000293f, 0x00002946, 0x00002972, + 0x0000297c, 0x000029ce, 0x000029de, 0x000029ee, + 0x00002a15, 0x00002a42, 0x00002a4a, 0x00002b29, + 0x00002b31, 0x00002b36, 0x00002b3f, 0x00002b48, + 0x00002b4e, 0x00002b57, 0x00002b61, 0x00002b68, + 0x00002b72, 0x00002b7e, 0x00002b8a, 0x00002b94, // Entry 160 - 17F - 0x00002bb5, 0x00002bd9, 0x00002bea, 0x00002c04, - 0x00002c13, 0x00002c27, 0x00002c35, 0x00002c68, - 0x00002c81, 0x00002c98, 0x00002cb7, 0x00002cc6, - 0x00002cce, 0x00002cde, 0x00002cf4, 0x00002d0c, - 0x00002d21, 0x00002d3e, 0x00002d55, 0x00002d70, - 0x00002d80, 0x00002d92, 0x00002da4, 0x00002db3, - 0x00002dc4, 0x00002de1, 0x00002e07, 0x00002e19, - 0x00002e30, 0x00002e4b, 0x00002e5b, 0x00002e70, + 0x00002bae, 0x00002bc8, 0x00002bec, 0x00002bfd, + 0x00002c17, 0x00002c26, 0x00002c3a, 0x00002c48, + 0x00002c7b, 0x00002c94, 0x00002cab, 0x00002cca, + 0x00002cd9, 0x00002ce1, 0x00002cf1, 0x00002d07, + 0x00002d1f, 0x00002d34, 0x00002d51, 0x00002d68, + 0x00002d83, 0x00002d93, 0x00002da5, 0x00002db7, + 0x00002dc6, 0x00002dd7, 0x00002df4, 0x00002e1a, + 0x00002e2c, 0x00002e43, 0x00002e5e, 0x00002e6e, // Entry 180 - 19F - 0x00002e84, 0x00002e97, 0x00002eaa, 0x00002ec1, - 0x00002ecd, 0x00002ee5, 0x00002ef4, 0x00002f01, - 0x00002f13, 0x00002f36, 0x00002f44, 0x00002f71, - 0x00002fa9, 0x00002fbe, 0x0000303d, 0x00003103, - 0x000031e4, 0x00003229, 0x00003252, 0x0000326f, - 0x0000328d, 0x000032c8, 0x000032d6, 0x000032ef, - 0x00003346, 0x00003373, 0x0000344f, 0x00003460, - 0x00003473, 0x0000347e, 0x0000348c, 0x00003499, + 0x00002e83, 0x00002e97, 0x00002eaa, 0x00002ebd, + 0x00002ed4, 0x00002ee0, 0x00002ef8, 0x00002f07, + 0x00002f14, 0x00002f26, 0x00002f49, 0x00002f57, + 0x00002f84, 0x00002fbc, 0x00002fd1, 0x00003050, + 0x00003116, 0x000031f7, 0x0000323c, 0x00003265, + 0x00003282, 0x000032a0, 0x000032db, 0x000032e9, + 0x00003302, 0x00003359, 0x00003386, 0x00003462, + 0x00003473, 0x00003486, 0x00003491, 0x0000349f, // Entry 1A0 - 1BF - 0x000034a7, 0x000034dd, 0x0000350c, 0x0000353d, - 0x00003555, 0x00003561, 0x00003568, 0x00003574, - 0x0000357c, 0x00003580, 0x0000358e, 0x00003599, - 0x000035a7, 0x000035bb, 0x000035fb, 0x00003617, - 0x00003625, 0x0000362b, 0x00003647, 0x0000364b, - 0x00003675, 0x00003688, 0x00003694, 0x0000369e, - 0x000036a3, 0x000036ab, 0x000036b4, 0x000036c8, - 0x000036d0, 0x000036df, 0x000036e6, 0x000036ed, + 0x000034ac, 0x000034ba, 0x000034f0, 0x0000351f, + 0x00003550, 0x00003568, 0x00003574, 0x0000357b, + 0x00003587, 0x0000358f, 0x00003593, 0x000035a1, + 0x000035ac, 0x000035ba, 0x000035ce, 0x0000360e, + 0x0000362a, 0x00003638, 0x0000363e, 0x0000365a, + 0x0000365e, 0x00003688, 0x0000369b, 0x000036a7, + 0x000036b1, 0x000036b6, 0x000036be, 0x000036c7, + 0x000036db, 0x000036e3, 0x000036f2, 0x000036f9, // Entry 1C0 - 1DF - 0x000036fd, 0x00003711, 0x0000371e, 0x0000373a, - 0x000037b5, 0x000037bc, 0x000037c4, 0x000037e6, - 0x000037fa, 0x00003805, 0x00003827, 0x00003832, - 0x0000383d, 0x00003876, 0x0000387b, 0x00003881, - 0x0000388d, 0x000038b1, 0x000038e5, 0x000038f7, - 0x00003935, 0x00003951, 0x00003986, 0x000039a0, - 0x000039d8, 0x000039e4, 0x000039ef, 0x000039fb, - 0x00003a01, 0x00003a0c, 0x00003a13, 0x00003a1b, + 0x00003700, 0x00003710, 0x00003724, 0x00003731, + 0x0000374d, 0x000037c8, 0x000037cf, 0x000037d7, + 0x000037f9, 0x0000380d, 0x00003818, 0x0000383a, + 0x00003845, 0x00003850, 0x00003889, 0x0000388e, + 0x00003894, 0x000038a0, 0x000038c4, 0x000038f8, + 0x0000390a, 0x00003948, 0x00003964, 0x00003999, + 0x000039b3, 0x000039eb, 0x000039f7, 0x00003a02, + 0x00003a0e, 0x00003a14, 0x00003a1f, 0x00003a26, // Entry 1E0 - 1FF - 0x00003a20, 0x00003a5f, 0x00003a6b, 0x00003a8c, - 0x00003ab5, 0x00003adb, 0x00003ae4, 0x00003af6, - 0x00003b4d, 0x00003b70, 0x00003ba8, 0x00003bb6, - 0x00003bc0, 0x00003bc9, 0x00003bda, 0x00003bdf, - 0x00003be2, 0x00003be9, 0x00003c61, 0x00003c71, - 0x00003c7e, 0x00003c8b, 0x00003c91, 0x00003c9c, - 0x00003cac, 0x00003cca, 0x00003cff, 0x00003d1f, - 0x00003d25, 0x00003d36, 0x00003d3a, 0x00003d43, + 0x00003a2e, 0x00003a33, 0x00003a72, 0x00003a7e, + 0x00003a9f, 0x00003ac8, 0x00003aee, 0x00003af7, + 0x00003b09, 0x00003b60, 0x00003b83, 0x00003bbb, + 0x00003bc9, 0x00003bd3, 0x00003bdc, 0x00003bed, + 0x00003bf2, 0x00003bf5, 0x00003bfc, 0x00003c74, + 0x00003c84, 0x00003c91, 0x00003c9e, 0x00003ca4, + 0x00003caf, 0x00003cbf, 0x00003cdd, 0x00003d12, + 0x00003d32, 0x00003d38, 0x00003d49, 0x00003d4d, // Entry 200 - 21F - 0x00003d50, 0x00003d5f, 0x00003d64, 0x00003d6b, - 0x00003d73, 0x00003d7a, 0x00003d81, 0x00003d88, - 0x00003dbb, 0x00003de5, 0x00003df2, 0x00003dfe, - 0x00003e27, 0x00003e52, 0x00003e5e, 0x00003e6a, - 0x00003e77, 0x00003e98, 0x00003ec9, 0x00003ed9, - 0x00003f13, 0x00003f31, 0x00003f5e, 0x00003f6a, - 0x00003f80, 0x00003f9b, 0x00003fba, 0x00003fe0, - 0x00003ff0, 0x00003fff, 0x0000400e, 0x00004046, + 0x00003d56, 0x00003d63, 0x00003d72, 0x00003d77, + 0x00003d7e, 0x00003d86, 0x00003d8d, 0x00003d94, + 0x00003d9b, 0x00003dce, 0x00003df8, 0x00003e05, + 0x00003e11, 0x00003e3a, 0x00003e65, 0x00003e71, + 0x00003e7d, 0x00003e8a, 0x00003eab, 0x00003edc, + 0x00003eec, 0x00003f26, 0x00003f44, 0x00003f71, + 0x00003f7d, 0x00003f93, 0x00003fae, 0x00003fcd, + 0x00003ff3, 0x00004003, 0x00004012, 0x00004021, // Entry 220 - 23F - 0x00004063, 0x0000408e, 0x0000409a, 0x000040a6, - 0x000040e1, 0x00004125, 0x00004130, 0x00004138, - 0x00004142, 0x0000414e, 0x00004155, 0x00004187, - 0x000041ad, 0x00004214, 0x0000426e, 0x00004293, - 0x000042ab, 0x000042e0, 0x0000431e, 0x00004361, - 0x0000437e, 0x000043b2, 0x0000441f, 0x00004452, - 0x0000445f, 0x00004470, 0x00004481, 0x00004493, - 0x000044e3, 0x000044ef, 0x000044f4, 0x00004511, + 0x00004059, 0x00004076, 0x000040a1, 0x000040ad, + 0x000040b9, 0x000040f4, 0x00004138, 0x00004143, + 0x0000414b, 0x00004155, 0x00004161, 0x00004168, + 0x0000419a, 0x000041c0, 0x00004227, 0x00004281, + 0x000042a6, 0x000042be, 0x000042f3, 0x00004331, + 0x00004374, 0x00004391, 0x000043c5, 0x00004432, + 0x00004465, 0x00004472, 0x00004483, 0x00004494, + 0x000044a6, 0x000044f6, 0x00004502, 0x00004507, // Entry 240 - 25F - 0x00004538, 0x00004544, 0x00004566, 0x0000458c, - 0x0000459c, 0x000045a1, 0x000045a8, 0x000045b0, - 0x000045bb, 0x000045c1, 0x000045c8, 0x000045d0, - 0x000045df, 0x000045e9, 0x000045f3, 0x00004603, - 0x00004617, 0x0000461d, 0x00004629, 0x0000462f, - 0x00004634, 0x00004639, 0x00004646, 0x0000464a, - 0x00004650, 0x0000465c, 0x00004691, 0x000046ab, - 0x000046d3, 0x000046e0, 0x000046e9, 0x000046f2, + 0x00004524, 0x0000454b, 0x00004557, 0x00004579, + 0x0000459f, 0x000045af, 0x000045b4, 0x000045bb, + 0x000045c3, 0x000045ce, 0x000045d4, 0x000045db, + 0x000045e3, 0x000045f2, 0x000045fc, 0x00004606, + 0x00004616, 0x0000462a, 0x00004630, 0x0000463c, + 0x00004642, 0x00004647, 0x0000464c, 0x00004659, + 0x0000465d, 0x00004663, 0x0000466f, 0x000046a4, + 0x000046be, 0x000046e6, 0x000046f3, 0x000046fc, // Entry 260 - 27F - 0x000046fe, 0x00004705, 0x00004710, 0x0000471f, - 0x00004725, 0x00004730, 0x0000473d, 0x0000475b, - 0x00004767, 0x00004788, 0x00004795, 0x0000479e, - 0x000047ac, 0x000047b5, 0x000047cf, 0x000047f7, - 0x00004806, 0x0000480d, 0x00004816, 0x0000482e, - 0x0000484a, 0x0000485a, 0x0000485f, 0x0000486b, - 0x00004881, 0x000048a6, 0x000048e9, 0x000048fc, - 0x00004929, 0x00004961, 0x0000499e, 0x000049cf, + 0x00004705, 0x00004711, 0x00004718, 0x00004723, + 0x00004732, 0x00004738, 0x00004743, 0x00004750, + 0x0000476e, 0x0000477a, 0x0000479b, 0x000047a8, + 0x000047b1, 0x000047bf, 0x000047c8, 0x000047e2, + 0x0000480a, 0x00004819, 0x00004820, 0x00004829, + 0x00004841, 0x0000485d, 0x0000486d, 0x00004872, + 0x0000487e, 0x00004894, 0x000048b9, 0x000048fc, + 0x0000490f, 0x0000493c, 0x00004974, 0x000049b1, // Entry 280 - 29F - 0x00004a26, 0x00004a33, 0x00004a91, 0x00004aa9, - 0x00004ac5, 0x00004adf, 0x00004af9, 0x00004b1d, - 0x00004b3b, 0x00004b51, 0x00004b67, 0x00004b7b, - 0x00004b90, 0x00004ba7, 0x00004bb8, 0x00004bdc, - 0x00004bec, 0x00004c0f, 0x00004c45, 0x00004c5c, - 0x00004c67, 0x00004c76, 0x00004c88, 0x00004c93, - 0x00004c9d, 0x00004cc5, 0x00004cd7, 0x00004cf8, - 0x00004d0a, 0x00004d2a, 0x00004d4f, 0x00004d69, + 0x000049e2, 0x00004a39, 0x00004a46, 0x00004aa4, + 0x00004abc, 0x00004ad8, 0x00004af2, 0x00004b0c, + 0x00004b30, 0x00004b4e, 0x00004b64, 0x00004b7a, + 0x00004b8e, 0x00004ba3, 0x00004bba, 0x00004bcb, + 0x00004bef, 0x00004bff, 0x00004c22, 0x00004c58, + 0x00004c6f, 0x00004c7a, 0x00004c89, 0x00004c9b, + 0x00004ca6, 0x00004cb0, 0x00004cd8, 0x00004cea, + 0x00004d0b, 0x00004d1d, 0x00004d3d, 0x00004d62, // Entry 2A0 - 2BF - 0x00004d81, 0x00004db1, 0x00004de7, 0x00004df3, - 0x00004e20, 0x00004e4f, 0x00004e58, 0x00004e69, - 0x00004e89, 0x00004ec7, 0x00004f19, 0x00004f77, - 0x00004fab, 0x00004fc6, 0x00004fdd, 0x00005000, - 0x0000502c, 0x0000504a, 0x00005065, 0x0000507f, - 0x000050a3, 0x000050bb, 0x000050df, 0x00005102, - 0x0000511a, -} // Size: 2812 bytes + 0x00004d7c, 0x00004d94, 0x00004dc4, 0x00004dfa, + 0x00004e06, 0x00004e33, 0x00004e62, 0x00004e6b, + 0x00004e7c, 0x00004e9c, 0x00004eda, 0x00004f2c, + 0x00004f8a, 0x00004fbe, 0x00004fd9, 0x00004ff0, + 0x00005013, 0x0000503f, 0x0000505d, 0x00005078, + 0x00005092, 0x000050b6, 0x000050ce, 0x000050f2, + 0x00005115, 0x0000512d, +} // Size: 2816 bytes -const enData string = "" + // Size: 20762 bytes +const enData string = "" + // Size: 20781 bytes "\x02Restricted Page\x02This function is only allowed for paid users. Ple" + "ase upgrade\x02Continue to Upgrade\x02Social bookmarking plus link shari" + "ng, shortening and listings all in one app.\x02Welcome to LinkTaco! Here" + @@ -1059,206 +1060,206 @@ const enData string = "" + // Size: 20762 bytes "can't create more than 5 qr codes per lists.\x02Short Not Found\x02You c" + "an't create more than 5 qr codes per shorts.\x02QR Code Not Found\x02Use" + "r follows %[1]s\x02This user does not follow this org\x02User unfollows " + - "%[1]s\x02Invalid orgType\x02Invalid level value.\x02Invalid status value" + - ".\x02A valid Organizaiton Slug is required.\x02Organization Slug is requ" + - "ired for user level domains\x04\x00\x01 \x0b\x02Invalid ID\x02Domain in " + - "use. Can not change service.\x02Name is required.\x02Email is required." + - "\x02Register Invitation\x02Linktaco: Invitation to Register\x02You have " + - "been invited by %[1]s to join Link Taco\x02Please click the link below:" + - "\x02You can not send both after and before cursors\x02Not Found\x02BaseU" + - "RL Not Found\x02Invalid tag cloud type without organization slug\x02Only" + - " members with read perm are allowed to perform this action\x02Unable to " + - "find suitable organization\x02Only superusers can fetch system level dom" + - "ains\x02Link Short Not Found\x02Invalid code type\x02Org slug is require" + - "d for this kind of token\x02Access Restricted\x02Access denied.\x02Organ" + - "ization not found.\x02Invalid listing ID provided\x02Invalid listing for" + - " specified organization\x02GraphQL Playground\x02Submit Query\x02Back Ho" + - "me\x02Invalid origin source for importer.\x02The file is required\x02The" + - " file submitted for this source should be html\x02The file submitted for" + - " this source should be json\x02Personal Access Tokens\x02Comment\x02Issu" + - "ed\x02Expired\x02Revoke\x02You have not created any personal access toke" + - "ns for your account.\x02Authorized Clients\x02Client Name\x02Grants\x02Y" + - "ou have not granted any third party clients access to your account.\x02A" + - "dd Personal Access Token\x02Note: Your access token will never b" + - "e shown to you again. Keep this secret. It will expire a year f" + - "rom now.\x02Revoke Personal Access Token\x02Do you want to revoke this p" + - "ersonal access token? This can not be undone.\x02Yes, do it\x02No, never" + - "mind\x02Successfully added personal access\x02Successfully revoked autho" + - "rization token.\x02Clients\x02Client ID\x02Manage\x02Add\x02No Clients" + - "\x02Add OAuth2 Client\x02Client Description\x02Redirect URL\x02Client UR" + - "L\x02Client Secret\x02Note: Your client secret will never be shown to yo" + - "u again.\x02OAuth 2.0 client management\x02Revoke tokens & client secret" + - "\x02If OAuth 2.0 bearer tokens issued for your OAuth client, or your cli" + - "ent secret, have been disclosed to a third-party, you must revoke all to" + - "kens and have replacements issued.\x02Revoke client tokens\x02Unregister" + - " this OAuth client\x02This will permanently unregister your OAuth 2.0 cl" + - "ient\x02revoke all tokens issued to it, and prohibit the issuance of new" + - " tokens.\x02Unregister\x02Description\x02Informative URL\x02OAuth 2.0 cl" + - "ient registered\x02Successfully added client\x02Successfully revoked cli" + - "ent.\x02Successfully reissued client.\x02Authorize\x02would like to acce" + - "ss to your Link Taco account.\x02is a third-party application operated b" + - "y\x02You may revoke this access at any time on the OAuth tab of your acc" + - "ount profile.\x02Scopes\x02Approve\x02Reject\x02LinkTaco - Your bookmark" + - " import is complete\x02Hi there,\x02Just wanted to let you know that you" + - "r bookmark import has completed successfully!\x02- LinkTaco Team\x02Inac" + - "tive Domain\x02The %[1]s domain is currently inactive\x02Please upgrade " + - "your account to reactivate it\x02Pricing\x02Every account can create unl" + - "imited organizations. Each organization has it's own bookmarks, listings" + - ", analytics, etc. All of the features below belong to each organization " + - "with their own unique URL's, groupings, and so on.\x02Feature\x02Free" + - "\x02Personal\x02Business\x02Price\x02per year\x02per month\x02months\x02" + - "Unlimited\x02Public only\x02Try It FREE\x02Bookmarks\x02Save public/priv" + - "ate links\x02Save public/private notes\x02Follow other organizations (so" + - "cial)\x02Organize by tags\x02Advanced filtering/search\x02Full RSS feeds" + - "\x02Custom domain + SSL\x02Link Listings\x02Create link listings (ie, so" + - "cial media bios, etc.)\x02Organize listings by tag\x02Filter/Search list" + - "ings\x02Unlimited QR codes per listing\x02Full Analytics\x02Listing\x02L" + - "ink Shortening\x02Unlimited short links\x02Organize shorts by tags\x02Fi" + - "lter/Search shorts\x02Unlimited QR codes per short\x02Full analytics his" + - "tory\x02QR Code specific analytics\x02Click analytics\x02Referer analyit" + - "cs\x02Country analytics\x02City analytics\x02Device analytics\x02Collabo" + - "ration / Integrations\x02Add unlimited members to organization\x02Slack " + - "Integration\x02MatterMost Integration\x02Build Your Own Integration\x02I" + - "mport / Export\x02Import from Pinboard\x02Import from Firefox\x02Import " + - "from Chrome\x02Import from Safari\x02Export in JSON or HTML\x02API Power" + - "ed\x02Full GraphQL API Access\x02OAuth2 Support\x02Self Hosting\x02Fully" + - " open source\x02Host your own version of Link Taco\x02Documentation\x02P" + - "ricing and feature details for LinkTaco.com\x02pricing, links, linktaco," + - " feature, plans, pricing plans\x02Welcome to LinkTaco!\x02Here you can m" + - "ix all your link saving and sharing needs in one tight little bundle. Mu" + - "ch like a taco. A link taco if you will.\x02LinkTaco is an open source p" + - "latform where you can host all of your links. Custom domains, QR codes, " + - "Analytics, full API, multiple organizations w/unlimited members are just" + - " some of what's included.\x02Social bookmarking is not new, it's just be" + - "en forgotten. Link shortening with analytics has been around forever. Li" + - "nk listings became cool once social media started allowing us to post a " + - "link to our websites in our profiles.\x02Up until now, all of these thin" + - "gs were hosted on different services.\x02Social bookmarking: Pinboard (D" + - "elicious)\x02Link shortening: Bitly et al\x02Link listings: Linktree et " + - "al\x02Peace Pinboard. Bye Bitly. Later Linktree. Hello LinkTaco!\x02Sinc" + - "e we're a\x02100% open source project\x04\x01 \x00R\x02you can host your" + - " own instance if you'd like full control over your own platform.\x02See " + - "the installation documentation for more.\x02Ready to get started? It's f" + - "ree to make an account and use it forever (with some limitations). To us" + - "e all features you have to pay just a few bucks a year, or a few per mon" + - "th if you're a business, and that's it. Simple!\x02Explore Features\x02O" + - "rganize Bookmarks\x02Link Lists\x02Collaboration\x02Integrations\x02Impo" + - "rt Export\x02Unlimited link listings (for social media bios, etc.)\x02Me" + - "mbers can add/edit/remove links (if allowed)\x02Members have access base" + - "d on permissions granted\x02Browser bookmark widget\x02Domain List\x02De" + - "lete\x02Lookup Name\x02Service\x02for\x02Link Shortner\x02No Domains\x02" + - "Create Domain\x02Migrate Short Links\x02Old links won't work. All code w" + - "ill be moved to the new domain.\x02Domain created successfully\x02Delete" + - " Domain\x02%[1]s\x02Domain successfully deleted\x02Yes\x02Do you really " + - "whant to delete this domain\x02Your Organizations\x02Open Source\x02Spon" + - "sored\x02Paid\x02Enabled\x02Disabled\x02Manage Subscription\x02Domains" + - "\x02Manage Members\x02Export\x02Import\x02Payment History\x02Create Orga" + - "nization\x02Org Username\x02Default Bookmark Visibility\x02Sorry, you ha" + - "ve exceeded the amount of free accounts available. Please update your cu" + - "rrent free account to create one more\x02Public\x02Private\x02Organizati" + - "on created successfully\x02Update Organization\x02Is Enabled\x02Organiza" + - "tion updated successfully\x02Add Member\x02Permission\x02Please upgrade " + - "to a Business organization to add members\x02Read\x02Write\x02Admin Writ" + - "e\x02An invitation was sent to this user\x02Something went wrong, imposs" + - "ible to send invitation\x02Delete Org Member\x02Something went wrong. Th" + - "is member could not be deleted: %[1]s\x02Member successfully deleted\x02" + - "Delete member %[1]s (%[2]s) from Organization %[3]s?\x02Member added suc" + - "cesxfully\x02Something went wrong. Impossible to get the member data\x02" + - "Member List\x02No members\x02Create Link\x02Title\x02Visibility\x02Unrea" + - "d\x02Starred\x02Tags\x02Use commas to separate your tags. Example: tag 1" + - ", tag 2, tag 3\x02Archive URL\x02A link was successfully created.\x02Err" + - "or fetching referenced url: Not found\x02Error fetching referenced link:" + - " %[1]v\x02bookmark\x02Popular Bookmarks\x02This ain't a popularity conte" + - "st or anything but this is weird that there are no links!\x02Most popula" + - "r links on LinkTaco.com\x02popular, links, linktaco, feature, plans, pri" + - "cing plans\x02Popular Links\x02Following\x02Unfollow\x02No organizations" + - "\x02Feed\x02By\x02Search\x02Your feed is empty :( Go follow some people." + - " Try the Popular or Recent feeds to find some interesting people to foll" + - "ow.\x02Advanced Search\x02Include Tags\x02Exclude Tags\x02Clear\x02Follo" + - "wings\x02Saved Bookmarks\x02This feed has no links. Booo!\x02Recent book" + - "marks for URL %[1]s added on LinkTaco.com\x02recent, public, links, link" + - "taco\x02saved\x02Recent Bookmarks\x02All\x02Untagged\x02Mark as read\x02" + - "Mark as unread\x02Star\x02Unstar\x02Archive\x02Follow\x02newest\x02oldes" + - "t\x02Recent public links added to %[1]s on LinkTaco.com\x02Recent public" + - " links added to LinkTaco.com\x02Recent Links\x02%[1]s Links\x02You have " + - "%[1]d restricted link(s) saved.\x02Upgrade the organization to activate " + - "them.\x02Link Detail\x02Public Post\x02Private Post\x02Bookmark '%[1]s' " + - "on LinkTaco.com\x02bookmark, note, detail, popular, links, linktaco\x02D" + - "elete Bookmark\x02Something went wrong. This bookmark could not be delet" + - "ed.\x02Bookmark successfully deleted\x02Do you really whant to delete th" + - "is bookmark?\x02Update Link\x02Do you want to delete\x02Link successfull" + - "y updated.\x02QR Codes powered by Link Taco!\x02You will be redirected i" + - "n 10 seconds.\x02QR Code Details\x02Download Image\x02Delete QR Code\x02" + - "Something went wrong. The QR Code could not be deleted.\x02QR Code succe" + - "ssfully deleted\x02Do you really whant to delete this qr code\x02Export " + - "Data\x02File format\x02This feature is not allowed for free user. Please" + - " upgrade.\x02As system admin run this command in the channel you want to" + - " connect\x02Disconnect\x02Connect\x02Connected\x02Import Data\x02Source" + - "\x02Click on Manage Bookmarks from the Bookmarks menu\x02A new window ca" + - "lled Library will open\x02In the left sidebar select the folder you want" + - " to export. To export all bookmarks select All Bookmarks\x02Click on the" + - " icon that has two arrows (up and down) and choose 'Export Bookmarks to " + - "HTML'\x02Go to the File menu and chose Export\x02Select Export Bookmarks" + - "\x02Go to the Bookmarks menu and choose Bookmark Manager\x02In the left " + - "sidebar select the folder that you want to export\x02In the top bookmark" + - " bar click on the three points at the top right\x02Click on on Export Bo" + - "okmarks\x02Go to https://pinboard.in/export/ and click on JSON\x02Your i" + - "mporting into a free account / organization, any private pinboard bookma" + - "rks will be marked restricted.\x02Upgrade your account to support privat" + - "e bookmarks.\x02Instructions\x02Safari Bookmarks\x02Chrome Bookmarks\x02" + - "Firefox Bookmarks\x02Your bookmark import is being processed. We will no" + - "tify you once it's complete.\x02Update Note\x02Note\x02Note '%[1]s' on L" + - "inkTaco.com\x02note, detail, popular, links, linktaco\x02Create Note\x02" + - "An note was successfully created.\x02Error fetching referenced note: %[1" + - "]v\x02Store Dashboard\x02Tour\x02Recent\x02Popular\x02Categories\x02Abou" + - "t\x02Log in\x02Log out\x02GQL Playground\x02Save Link\x02Save Note\x02Pe" + - "rsonal Tokens\x02Client Applications\x02Lists\x02Short Links\x02Admin" + - "\x02Help\x02Blog\x02Update Links\x02URL\x02Order\x02Delete List\x02Somet" + - "hing went wrong. The link could not be deleted.\x02Link successfully del" + - "eted\x02Do you really whant to delete this link\x02Create Links\x02Previ" + - "ous\x02No Links\x02Update List\x02Domain\x02Is Default\x02Delete Picture" + - "\x02Other\x02Other Name\x02Social Links\x02Listing successfully updated." + - "\x02Create List\x02A list was successfully created.\x02Manage Links\x02N" + - "o Lists\x02Creation Date\x02QR Codes\x02List successfully deleted\x02Do " + - "you really whant to delete this list\x02Create QR Code\x02Create\x02Down" + - "load\x02Custom background image\x02QR Code succesfully created\x02QR Cod" + - "e Listing\x02View\x02No QR Codes\x02Disconnect Mattermost\x02Mattermost " + - "successfully disconnected\x02Do you really want to disconnect this organ" + - "ization from mattermost\x02Connect Mattermost\x02This team is already ti" + - "ed to an organization\x02Do you want to connect this organization to mat" + - "termost?\x02This feature is restricted to free accounts. Please upgrade." + - "\x02Organization linked successfully with mattermost\x02Sorry, free acco" + - "unts do not support Mattermost Integration. Please upgrade to continue" + - "\x02Connect User\x02In order to interact with the mattermost you have to" + - " connect your account with your link user\x02Do you want to proceed?\x02" + - "User connected successfully\x02No slack connection found\x02We sent you " + - "a private msg\x02The text to be searched is required\x02No links were fo" + - "und for %[1]s\x02No organization found\x02The title is required\x02The u" + - "rl is required\x02The code is required\x02The domain is required\x02Doma" + - "in not found\x02A new short was created succesfully\x02Url is required" + - "\x02A new link was created succesfully\x02Please click in the following " + - "link to tie a org %[1]s\x02Installed successfully\x02Short Link\x02No Sh" + - "ort Links\x02Create Short Link\x02Short Code\x02No Domain\x02An short li" + - "nk was successfully created.\x02Update Short Link\x02Short link successf" + - "ully updated.\x02Delete Short Link\x02Short Link successfully deleted" + - "\x02URL Shortening powered by Link Taco!\x02No URL argument was given" + - "\x02%[1]s: domain not found\x02Your short link was successfully created:" + - " %[1]s\x02Your link was successfully saved. Details here: %[1]s\x02Link " + - "Search\x02Please link your slack user with link: %[1]s\x02We sent you a " + - "direct message with instructions\x02Add Link\x02Disconnect Slack\x02Slac" + - "k successfully disconnected\x02Do you really want to disconnect this org" + - "anization from slack\x02Sorry, free accounts do not support Slack Integr" + - "ation. Please upgrade to continue\x02In order to interact with Link Taco" + - " you have to connect you slack account with your link user\x02Something " + - "went wrong. The user could not be linked.\x02Connect to Slack Workspace" + - "\x02Invalid slack response\x02Do you want to connect with slack?\x02Orga" + - "nization linked successfully with slack\x02Invalid email and/or password" + - "\x02New passwords do not match\x02User is not authenticated\x02Current p" + - "assword given is incorrect\x02This field is required.\x02Please enter a " + - "valid email address.\x02Please enter a valid phone number.\x02Failed the" + - " '%[1]s' tag." + "%[1]s\x02Invalid orgType\x02Invalid visibility\x02Invalid level value." + + "\x02Invalid status value.\x02A valid Organizaiton Slug is required.\x02O" + + "rganization Slug is required for user level domains\x04\x00\x01 \x0b\x02" + + "Invalid ID\x02Domain in use. Can not change service.\x02Name is required" + + ".\x02Email is required.\x02Register Invitation\x02Linktaco: Invitation t" + + "o Register\x02You have been invited by %[1]s to join Link Taco\x02Please" + + " click the link below:\x02You can not send both after and before cursors" + + "\x02Not Found\x02BaseURL Not Found\x02Invalid tag cloud type without org" + + "anization slug\x02Only members with read perm are allowed to perform thi" + + "s action\x02Unable to find suitable organization\x02Only superusers can " + + "fetch system level domains\x02Link Short Not Found\x02Invalid code type" + + "\x02Org slug is required for this kind of token\x02Access Restricted\x02" + + "Access denied.\x02Organization not found.\x02Invalid listing ID provided" + + "\x02Invalid listing for specified organization\x02GraphQL Playground\x02" + + "Submit Query\x02Back Home\x02Invalid origin source for importer.\x02The " + + "file is required\x02The file submitted for this source should be html" + + "\x02The file submitted for this source should be json\x02Personal Access" + + " Tokens\x02Comment\x02Issued\x02Expired\x02Revoke\x02You have not create" + + "d any personal access tokens for your account.\x02Authorized Clients\x02" + + "Client Name\x02Grants\x02You have not granted any third party clients ac" + + "cess to your account.\x02Add Personal Access Token\x02Note: Your access " + + "token will never be shown to you again. Keep this secre" + + "t. It will expire a year from now.\x02Revoke Personal Access Token\x02Do" + + " you want to revoke this personal access token? This can not be undone." + + "\x02Yes, do it\x02No, nevermind\x02Successfully added personal access" + + "\x02Successfully revoked authorization token.\x02Clients\x02Client ID" + + "\x02Manage\x02Add\x02No Clients\x02Add OAuth2 Client\x02Client Descripti" + + "on\x02Redirect URL\x02Client URL\x02Client Secret\x02Note: Your client s" + + "ecret will never be shown to you again.\x02OAuth 2.0 client management" + + "\x02Revoke tokens & client secret\x02If OAuth 2.0 bearer tokens issued f" + + "or your OAuth client, or your client secret, have been disclosed to a th" + + "ird-party, you must revoke all tokens and have replacements issued.\x02R" + + "evoke client tokens\x02Unregister this OAuth client\x02This will permane" + + "ntly unregister your OAuth 2.0 client\x02revoke all tokens issued to it," + + " and prohibit the issuance of new tokens.\x02Unregister\x02Description" + + "\x02Informative URL\x02OAuth 2.0 client registered\x02Successfully added" + + " client\x02Successfully revoked client.\x02Successfully reissued client." + + "\x02Authorize\x02would like to access to your Link Taco account.\x02is a" + + " third-party application operated by\x02You may revoke this access at an" + + "y time on the OAuth tab of your account profile.\x02Scopes\x02Approve" + + "\x02Reject\x02LinkTaco - Your bookmark import is complete\x02Hi there," + + "\x02Just wanted to let you know that your bookmark import has completed " + + "successfully!\x02- LinkTaco Team\x02Inactive Domain\x02The %[1]s domain " + + "is currently inactive\x02Please upgrade your account to reactivate it" + + "\x02Pricing\x02Every account can create unlimited organizations. Each or" + + "ganization has it's own bookmarks, listings, analytics, etc. All of the " + + "features below belong to each organization with their own unique URL's, " + + "groupings, and so on.\x02Feature\x02Free\x02Personal\x02Business\x02Pric" + + "e\x02per year\x02per month\x02months\x02Unlimited\x02Public only\x02Try " + + "It FREE\x02Bookmarks\x02Save public/private links\x02Save public/private" + + " notes\x02Follow other organizations (social)\x02Organize by tags\x02Adv" + + "anced filtering/search\x02Full RSS feeds\x02Custom domain + SSL\x02Link " + + "Listings\x02Create link listings (ie, social media bios, etc.)\x02Organi" + + "ze listings by tag\x02Filter/Search listings\x02Unlimited QR codes per l" + + "isting\x02Full Analytics\x02Listing\x02Link Shortening\x02Unlimited shor" + + "t links\x02Organize shorts by tags\x02Filter/Search shorts\x02Unlimited " + + "QR codes per short\x02Full analytics history\x02QR Code specific analyti" + + "cs\x02Click analytics\x02Referer analyitcs\x02Country analytics\x02City " + + "analytics\x02Device analytics\x02Collaboration / Integrations\x02Add unl" + + "imited members to organization\x02Slack Integration\x02MatterMost Integr" + + "ation\x02Build Your Own Integration\x02Import / Export\x02Import from Pi" + + "nboard\x02Import from Firefox\x02Import from Chrome\x02Import from Safar" + + "i\x02Export in JSON or HTML\x02API Powered\x02Full GraphQL API Access" + + "\x02OAuth2 Support\x02Self Hosting\x02Fully open source\x02Host your own" + + " version of Link Taco\x02Documentation\x02Pricing and feature details fo" + + "r LinkTaco.com\x02pricing, links, linktaco, feature, plans, pricing plan" + + "s\x02Welcome to LinkTaco!\x02Here you can mix all your link saving and s" + + "haring needs in one tight little bundle. Much like a taco. A link taco i" + + "f you will.\x02LinkTaco is an open source platform where you can host al" + + "l of your links. Custom domains, QR codes, Analytics, full API, multiple" + + " organizations w/unlimited members are just some of what's included.\x02" + + "Social bookmarking is not new, it's just been forgotten. Link shortening" + + " with analytics has been around forever. Link listings became cool once " + + "social media started allowing us to post a link to our websites in our p" + + "rofiles.\x02Up until now, all of these things were hosted on different s" + + "ervices.\x02Social bookmarking: Pinboard (Delicious)\x02Link shortening:" + + " Bitly et al\x02Link listings: Linktree et al\x02Peace Pinboard. Bye Bit" + + "ly. Later Linktree. Hello LinkTaco!\x02Since we're a\x02100% open source" + + " project\x04\x01 \x00R\x02you can host your own instance if you'd like f" + + "ull control over your own platform.\x02See the installation documentatio" + + "n for more.\x02Ready to get started? It's free to make an account and us" + + "e it forever (with some limitations). To use all features you have to pa" + + "y just a few bucks a year, or a few per month if you're a business, and " + + "that's it. Simple!\x02Explore Features\x02Organize Bookmarks\x02Link Lis" + + "ts\x02Collaboration\x02Integrations\x02Import Export\x02Unlimited link l" + + "istings (for social media bios, etc.)\x02Members can add/edit/remove lin" + + "ks (if allowed)\x02Members have access based on permissions granted\x02B" + + "rowser bookmark widget\x02Domain List\x02Delete\x02Lookup Name\x02Servic" + + "e\x02for\x02Link Shortner\x02No Domains\x02Create Domain\x02Migrate Shor" + + "t Links\x02Old links won't work. All code will be moved to the new domai" + + "n.\x02Domain created successfully\x02Delete Domain\x02%[1]s\x02Domain su" + + "ccessfully deleted\x02Yes\x02Do you really whant to delete this domain" + + "\x02Your Organizations\x02Open Source\x02Sponsored\x02Paid\x02Enabled" + + "\x02Disabled\x02Manage Subscription\x02Domains\x02Manage Members\x02Expo" + + "rt\x02Import\x02Payment History\x02Create Organization\x02Org Username" + + "\x02Default Bookmark Visibility\x02Sorry, you have exceeded the amount o" + + "f free accounts available. Please update your current free account to cr" + + "eate one more\x02Public\x02Private\x02Organization created successfully" + + "\x02Update Organization\x02Is Enabled\x02Organization updated successful" + + "ly\x02Add Member\x02Permission\x02Please upgrade to a Business organizat" + + "ion to add members\x02Read\x02Write\x02Admin Write\x02An invitation was " + + "sent to this user\x02Something went wrong, impossible to send invitation" + + "\x02Delete Org Member\x02Something went wrong. This member could not be " + + "deleted: %[1]s\x02Member successfully deleted\x02Delete member %[1]s (%[" + + "2]s) from Organization %[3]s?\x02Member added succesxfully\x02Something " + + "went wrong. Impossible to get the member data\x02Member List\x02No membe" + + "rs\x02Create Link\x02Title\x02Visibility\x02Unread\x02Starred\x02Tags" + + "\x02Use commas to separate your tags. Example: tag 1, tag 2, tag 3\x02Ar" + + "chive URL\x02A link was successfully created.\x02Error fetching referenc" + + "ed url: Not found\x02Error fetching referenced link: %[1]v\x02bookmark" + + "\x02Popular Bookmarks\x02This ain't a popularity contest or anything but" + + " this is weird that there are no links!\x02Most popular links on LinkTac" + + "o.com\x02popular, links, linktaco, feature, plans, pricing plans\x02Popu" + + "lar Links\x02Following\x02Unfollow\x02No organizations\x02Feed\x02By\x02" + + "Search\x02Your feed is empty :( Go follow some people. Try the Popular o" + + "r Recent feeds to find some interesting people to follow.\x02Advanced Se" + + "arch\x02Include Tags\x02Exclude Tags\x02Clear\x02Followings\x02Saved Boo" + + "kmarks\x02This feed has no links. Booo!\x02Recent bookmarks for URL %[1]" + + "s added on LinkTaco.com\x02recent, public, links, linktaco\x02saved\x02R" + + "ecent Bookmarks\x02All\x02Untagged\x02Mark as read\x02Mark as unread\x02" + + "Star\x02Unstar\x02Archive\x02Follow\x02newest\x02oldest\x02Recent public" + + " links added to %[1]s on LinkTaco.com\x02Recent public links added to Li" + + "nkTaco.com\x02Recent Links\x02%[1]s Links\x02You have %[1]d restricted l" + + "ink(s) saved.\x02Upgrade the organization to activate them.\x02Link Deta" + + "il\x02Public Post\x02Private Post\x02Bookmark '%[1]s' on LinkTaco.com" + + "\x02bookmark, note, detail, popular, links, linktaco\x02Delete Bookmark" + + "\x02Something went wrong. This bookmark could not be deleted.\x02Bookmar" + + "k successfully deleted\x02Do you really whant to delete this bookmark?" + + "\x02Update Link\x02Do you want to delete\x02Link successfully updated." + + "\x02QR Codes powered by Link Taco!\x02You will be redirected in 10 secon" + + "ds.\x02QR Code Details\x02Download Image\x02Delete QR Code\x02Something " + + "went wrong. The QR Code could not be deleted.\x02QR Code successfully de" + + "leted\x02Do you really whant to delete this qr code\x02Export Data\x02Fi" + + "le format\x02This feature is not allowed for free user. Please upgrade." + + "\x02As system admin run this command in the channel you want to connect" + + "\x02Disconnect\x02Connect\x02Connected\x02Import Data\x02Source\x02Click" + + " on Manage Bookmarks from the Bookmarks menu\x02A new window called Libr" + + "ary will open\x02In the left sidebar select the folder you want to expor" + + "t. To export all bookmarks select All Bookmarks\x02Click on the icon tha" + + "t has two arrows (up and down) and choose 'Export Bookmarks to HTML'\x02" + + "Go to the File menu and chose Export\x02Select Export Bookmarks\x02Go to" + + " the Bookmarks menu and choose Bookmark Manager\x02In the left sidebar s" + + "elect the folder that you want to export\x02In the top bookmark bar clic" + + "k on the three points at the top right\x02Click on on Export Bookmarks" + + "\x02Go to https://pinboard.in/export/ and click on JSON\x02Your importin" + + "g into a free account / organization, any private pinboard bookmarks wil" + + "l be marked restricted.\x02Upgrade your account to support private bookm" + + "arks.\x02Instructions\x02Safari Bookmarks\x02Chrome Bookmarks\x02Firefox" + + " Bookmarks\x02Your bookmark import is being processed. We will notify yo" + + "u once it's complete.\x02Update Note\x02Note\x02Note '%[1]s' on LinkTaco" + + ".com\x02note, detail, popular, links, linktaco\x02Create Note\x02An note" + + " was successfully created.\x02Error fetching referenced note: %[1]v\x02S" + + "tore Dashboard\x02Tour\x02Recent\x02Popular\x02Categories\x02About\x02Lo" + + "g in\x02Log out\x02GQL Playground\x02Save Link\x02Save Note\x02Personal " + + "Tokens\x02Client Applications\x02Lists\x02Short Links\x02Admin\x02Help" + + "\x02Blog\x02Update Links\x02URL\x02Order\x02Delete List\x02Something wen" + + "t wrong. The link could not be deleted.\x02Link successfully deleted\x02" + + "Do you really whant to delete this link\x02Create Links\x02Previous\x02N" + + "o Links\x02Update List\x02Domain\x02Is Default\x02Delete Picture\x02Othe" + + "r\x02Other Name\x02Social Links\x02Listing successfully updated.\x02Crea" + + "te List\x02A list was successfully created.\x02Manage Links\x02No Lists" + + "\x02Creation Date\x02QR Codes\x02List successfully deleted\x02Do you rea" + + "lly whant to delete this list\x02Create QR Code\x02Create\x02Download" + + "\x02Custom background image\x02QR Code succesfully created\x02QR Code Li" + + "sting\x02View\x02No QR Codes\x02Disconnect Mattermost\x02Mattermost succ" + + "essfully disconnected\x02Do you really want to disconnect this organizat" + + "ion from mattermost\x02Connect Mattermost\x02This team is already tied t" + + "o an organization\x02Do you want to connect this organization to matterm" + + "ost?\x02This feature is restricted to free accounts. Please upgrade.\x02" + + "Organization linked successfully with mattermost\x02Sorry, free accounts" + + " do not support Mattermost Integration. Please upgrade to continue\x02Co" + + "nnect User\x02In order to interact with the mattermost you have to conne" + + "ct your account with your link user\x02Do you want to proceed?\x02User c" + + "onnected successfully\x02No slack connection found\x02We sent you a priv" + + "ate msg\x02The text to be searched is required\x02No links were found fo" + + "r %[1]s\x02No organization found\x02The title is required\x02The url is " + + "required\x02The code is required\x02The domain is required\x02Domain not" + + " found\x02A new short was created succesfully\x02Url is required\x02A ne" + + "w link was created succesfully\x02Please click in the following link to " + + "tie a org %[1]s\x02Installed successfully\x02Short Link\x02No Short Link" + + "s\x02Create Short Link\x02Short Code\x02No Domain\x02An short link was s" + + "uccessfully created.\x02Update Short Link\x02Short link successfully upd" + + "ated.\x02Delete Short Link\x02Short Link successfully deleted\x02URL Sho" + + "rtening powered by Link Taco!\x02No URL argument was given\x02%[1]s: dom" + + "ain not found\x02Your short link was successfully created: %[1]s\x02Your" + + " link was successfully saved. Details here: %[1]s\x02Link Search\x02Plea" + + "se link your slack user with link: %[1]s\x02We sent you a direct message" + + " with instructions\x02Add Link\x02Disconnect Slack\x02Slack successfully" + + " disconnected\x02Do you really want to disconnect this organization from" + + " slack\x02Sorry, free accounts do not support Slack Integration. Please " + + "upgrade to continue\x02In order to interact with Link Taco you have to c" + + "onnect you slack account with your link user\x02Something went wrong. Th" + + "e user could not be linked.\x02Connect to Slack Workspace\x02Invalid sla" + + "ck response\x02Do you want to connect with slack?\x02Organization linked" + + " successfully with slack\x02Invalid email and/or password\x02New passwor" + + "ds do not match\x02User is not authenticated\x02Current password given i" + + "s incorrect\x02This field is required.\x02Please enter a valid email add" + + "ress.\x02Please enter a valid phone number.\x02Failed the '%[1]s' tag." -var esIndex = []uint32{ // 697 elements +var esIndex = []uint32{ // 698 elements // Entry 0 - 1F 0x00000000, 0x00000014, 0x0000006a, 0x00000089, 0x000000e0, 0x00000199, 0x00000233, 0x000002a4, @@ -1328,137 +1329,137 @@ var esIndex = []uint32{ // 697 elements 0x0000248c, 0x000024a9, 0x000024be, 0x000024d7, 0x000024f1, 0x00002505, 0x00002535, 0x0000254e, 0x0000257f, 0x00002598, 0x000025b1, 0x000025dc, - 0x000025f8, 0x0000260a, 0x00002623, 0x0000263d, - 0x0000266b, 0x000026b0, 0x000026c2, 0x000026fc, - 0x00002710, 0x00002723, 0x0000273b, 0x0000275d, + 0x000025f8, 0x0000260a, 0x00002621, 0x0000263a, + 0x00002654, 0x00002682, 0x000026c7, 0x000026d9, + 0x00002713, 0x00002727, 0x0000273a, 0x00002752, // Entry 100 - 11F - 0x00002791, 0x000027b9, 0x000027ec, 0x000027fa, - 0x00002810, 0x0000285d, 0x000028a3, 0x000028cd, - 0x00002910, 0x00002929, 0x00002943, 0x00002981, - 0x00002994, 0x000029a5, 0x000029c2, 0x000029e9, - 0x00002a1f, 0x00002a3a, 0x00002a4b, 0x00002a5d, - 0x00002a8c, 0x00002aa4, 0x00002adc, 0x00002b10, - 0x00002b2a, 0x00002b35, 0x00002b3c, 0x00002b45, - 0x00002b4d, 0x00002b8b, 0x00002ba0, 0x00002bb2, + 0x00002774, 0x000027a8, 0x000027d0, 0x00002803, + 0x00002811, 0x00002827, 0x00002874, 0x000028ba, + 0x000028e4, 0x00002927, 0x00002940, 0x0000295a, + 0x00002998, 0x000029ab, 0x000029bc, 0x000029d9, + 0x00002a00, 0x00002a36, 0x00002a51, 0x00002a62, + 0x00002a74, 0x00002aa3, 0x00002abb, 0x00002af3, + 0x00002b27, 0x00002b41, 0x00002b4c, 0x00002b53, + 0x00002b5c, 0x00002b64, 0x00002ba2, 0x00002bb7, // Entry 120 - 13F - 0x00002bba, 0x00002c01, 0x00002c22, 0x00002c9f, - 0x00002cc0, 0x00002d12, 0x00002d1c, 0x00002d1f, - 0x00002d43, 0x00002d6e, 0x00002d77, 0x00002d85, - 0x00002d8d, 0x00002d95, 0x00002da2, 0x00002db9, - 0x00002dd1, 0x00002deb, 0x00002dfa, 0x00002e09, - 0x00002e41, 0x00002e5f, 0x00002e80, 0x00002f41, - 0x00002f5b, 0x00002f7a, 0x00002fb7, 0x00003003, - 0x00003010, 0x0000301d, 0x0000302d, 0x0000304d, + 0x00002bc9, 0x00002bd1, 0x00002c18, 0x00002c39, + 0x00002cb6, 0x00002cd7, 0x00002d29, 0x00002d33, + 0x00002d36, 0x00002d5a, 0x00002d85, 0x00002d8e, + 0x00002d9c, 0x00002da4, 0x00002dac, 0x00002db9, + 0x00002dd0, 0x00002de8, 0x00002e02, 0x00002e11, + 0x00002e20, 0x00002e58, 0x00002e76, 0x00002e97, + 0x00002f58, 0x00002f72, 0x00002f91, 0x00002fce, + 0x0000301a, 0x00003027, 0x00003034, 0x00003044, // Entry 140 - 15F - 0x00003069, 0x00003085, 0x000030a1, 0x000030ab, - 0x000030d6, 0x00003102, 0x00003152, 0x0000315a, - 0x00003162, 0x0000316b, 0x000031a8, 0x000031ae, - 0x0000320c, 0x00003221, 0x00003232, 0x00003261, - 0x000032a4, 0x000032ac, 0x000033a8, 0x000033b6, - 0x000033bd, 0x000033c6, 0x000033ce, 0x000033d5, - 0x000033de, 0x000033e6, 0x000033ec, 0x000033f6, - 0x00003404, 0x00003415, 0x00003420, 0x00003443, + 0x00003064, 0x00003080, 0x0000309c, 0x000030b8, + 0x000030c2, 0x000030ed, 0x00003119, 0x00003169, + 0x00003171, 0x00003179, 0x00003182, 0x000031bf, + 0x000031c5, 0x00003223, 0x00003238, 0x00003249, + 0x00003278, 0x000032bb, 0x000032c3, 0x000033bf, + 0x000033cd, 0x000033d4, 0x000033dd, 0x000033e5, + 0x000033ec, 0x000033f5, 0x000033fd, 0x00003403, + 0x0000340d, 0x0000341b, 0x0000342c, 0x00003437, // Entry 160 - 17F - 0x00003464, 0x00003489, 0x000034a1, 0x000034be, - 0x000034d4, 0x000034f0, 0x00003504, 0x00003551, - 0x00003572, 0x0000358a, 0x000035ad, 0x000035c0, - 0x000035c8, 0x000035e0, 0x000035fa, 0x00003621, - 0x0000363f, 0x00003667, 0x00003687, 0x000036ad, - 0x000036c0, 0x000036d7, 0x000036eb, 0x00003700, - 0x0000371a, 0x00003738, 0x00003767, 0x0000377e, - 0x0000379a, 0x000037bb, 0x000037cf, 0x000037e7, + 0x0000345a, 0x0000347b, 0x000034a0, 0x000034b8, + 0x000034d5, 0x000034eb, 0x00003507, 0x0000351b, + 0x00003568, 0x00003589, 0x000035a1, 0x000035c4, + 0x000035d7, 0x000035df, 0x000035f7, 0x00003611, + 0x00003638, 0x00003656, 0x0000367e, 0x0000369e, + 0x000036c4, 0x000036d7, 0x000036ee, 0x00003702, + 0x00003717, 0x00003731, 0x0000374f, 0x0000377e, + 0x00003795, 0x000037b1, 0x000037d2, 0x000037e6, // Entry 180 - 19F - 0x000037fe, 0x00003814, 0x0000382a, 0x00003842, - 0x00003854, 0x00003875, 0x00003884, 0x00003897, - 0x000038b5, 0x000038dd, 0x000038ec, 0x00003925, - 0x0000396d, 0x00003986, 0x00003a22, 0x00003b1c, - 0x00003c38, 0x00003c7c, 0x00003ca6, 0x00003ccd, - 0x00003cf3, 0x00003d34, 0x00003d42, 0x00003d63, - 0x00003dc4, 0x00003e07, 0x00003eff, 0x00003f13, - 0x00003f28, 0x00003f37, 0x00003f45, 0x00003f53, + 0x000037fe, 0x00003815, 0x0000382b, 0x00003841, + 0x00003859, 0x0000386b, 0x0000388c, 0x0000389b, + 0x000038ae, 0x000038cc, 0x000038f4, 0x00003903, + 0x0000393c, 0x00003984, 0x0000399d, 0x00003a39, + 0x00003b33, 0x00003c4f, 0x00003c93, 0x00003cbd, + 0x00003ce4, 0x00003d0a, 0x00003d4b, 0x00003d59, + 0x00003d7a, 0x00003ddb, 0x00003e1e, 0x00003f16, + 0x00003f2a, 0x00003f3f, 0x00003f4e, 0x00003f5c, // Entry 1A0 - 1BF - 0x00003f65, 0x00003faf, 0x00003ff3, 0x0000402c, - 0x0000404f, 0x00004060, 0x00004069, 0x0000407d, - 0x00004086, 0x0000408b, 0x00004097, 0x000040a4, - 0x000040b2, 0x000040c6, 0x0000411d, 0x00004137, - 0x00004148, 0x0000414e, 0x0000416a, 0x0000416d, - 0x00004189, 0x0000419c, 0x000041ac, 0x000041b8, - 0x000041bf, 0x000041c8, 0x000041d4, 0x000041ea, - 0x000041f3, 0x00004204, 0x0000420d, 0x00004216, + 0x00003f6a, 0x00003f7c, 0x00003fc6, 0x0000400a, + 0x00004043, 0x00004066, 0x00004077, 0x00004080, + 0x00004094, 0x0000409d, 0x000040a2, 0x000040ae, + 0x000040bb, 0x000040c9, 0x000040dd, 0x00004134, + 0x0000414e, 0x0000415f, 0x00004165, 0x00004181, + 0x00004184, 0x000041a0, 0x000041b3, 0x000041c3, + 0x000041cf, 0x000041d6, 0x000041df, 0x000041eb, + 0x00004201, 0x0000420a, 0x0000421b, 0x00004224, // Entry 1C0 - 1DF - 0x00004229, 0x0000423d, 0x00004260, 0x00004289, - 0x00004308, 0x00004311, 0x00004319, 0x00004339, - 0x00004352, 0x00004363, 0x00004388, 0x00004398, - 0x000043a0, 0x000043de, 0x000043e3, 0x000043ec, - 0x00004407, 0x00004432, 0x00004460, 0x00004485, - 0x000044c0, 0x000044dd, 0x0000451c, 0x00004538, - 0x00004571, 0x00004583, 0x00004590, 0x0000459d, - 0x000045a5, 0x000045b1, 0x000045ba, 0x000045c4, + 0x0000422d, 0x00004240, 0x00004254, 0x00004277, + 0x000042a0, 0x0000431f, 0x00004328, 0x00004330, + 0x00004350, 0x00004369, 0x0000437a, 0x0000439f, + 0x000043af, 0x000043b7, 0x000043f5, 0x000043fa, + 0x00004403, 0x0000441e, 0x00004449, 0x00004477, + 0x0000449c, 0x000044d7, 0x000044f4, 0x00004533, + 0x0000454f, 0x00004588, 0x0000459a, 0x000045a7, + 0x000045b4, 0x000045bc, 0x000045c8, 0x000045d1, // Entry 1E0 - 1FF - 0x000045ce, 0x00004620, 0x0000462f, 0x0000464d, - 0x0000467d, 0x000046a4, 0x000046ad, 0x000046c2, - 0x0000471a, 0x00004741, 0x0000478b, 0x0000479b, - 0x000047a5, 0x000047b5, 0x000047c8, 0x000047cd, - 0x000047d1, 0x000047d8, 0x0000485c, 0x0000486f, - 0x0000487c, 0x00004889, 0x00004891, 0x0000489b, - 0x000048b0, 0x000048d4, 0x00004915, 0x0000493d, - 0x00004946, 0x0000495b, 0x00004961, 0x0000496f, + 0x000045db, 0x000045e5, 0x00004637, 0x00004646, + 0x00004664, 0x00004694, 0x000046bb, 0x000046c4, + 0x000046d9, 0x00004731, 0x00004758, 0x000047a2, + 0x000047b2, 0x000047bc, 0x000047cc, 0x000047df, + 0x000047e4, 0x000047e8, 0x000047ef, 0x00004873, + 0x00004886, 0x00004893, 0x000048a0, 0x000048a8, + 0x000048b2, 0x000048c7, 0x000048eb, 0x0000492c, + 0x00004954, 0x0000495d, 0x00004972, 0x00004978, // Entry 200 - 21F - 0x00004982, 0x00004998, 0x000049a1, 0x000049ad, - 0x000049b6, 0x000049bd, 0x000049c8, 0x000049d3, - 0x00004a11, 0x00004a46, 0x00004a56, 0x00004a64, - 0x00004a90, 0x00004abc, 0x00004ace, 0x00004ae4, - 0x00004afa, 0x00004b1b, 0x00004b4f, 0x00004b5f, - 0x00004b93, 0x00004bb1, 0x00004bdc, 0x00004bee, - 0x00004bfd, 0x00004c19, 0x00004c33, 0x00004c59, - 0x00004c70, 0x00004c7e, 0x00004c91, 0x00004cc7, + 0x00004986, 0x00004999, 0x000049af, 0x000049b8, + 0x000049c4, 0x000049cd, 0x000049d4, 0x000049df, + 0x000049ea, 0x00004a28, 0x00004a5d, 0x00004a6d, + 0x00004a7b, 0x00004aa7, 0x00004ad3, 0x00004ae5, + 0x00004afb, 0x00004b11, 0x00004b32, 0x00004b66, + 0x00004b76, 0x00004baa, 0x00004bc8, 0x00004bf3, + 0x00004c05, 0x00004c14, 0x00004c30, 0x00004c4a, + 0x00004c70, 0x00004c87, 0x00004c95, 0x00004ca8, // Entry 220 - 23F - 0x00004ce6, 0x00004d05, 0x00004d14, 0x00004d27, - 0x00004d76, 0x00004dd0, 0x00004ddc, 0x00004de5, - 0x00004def, 0x00004dfe, 0x00004e05, 0x00004e3e, - 0x00004e6e, 0x00004efa, 0x00004f52, 0x00004f7e, - 0x00004f9c, 0x00004fd2, 0x0000501c, 0x0000506d, - 0x0000508a, 0x000050c0, 0x0000513b, 0x00005171, - 0x0000517f, 0x00005194, 0x000051a9, 0x000051bf, - 0x00005218, 0x00005228, 0x0000522d, 0x0000524a, + 0x00004cde, 0x00004cfd, 0x00004d1c, 0x00004d2b, + 0x00004d3e, 0x00004d8d, 0x00004de7, 0x00004df3, + 0x00004dfc, 0x00004e06, 0x00004e15, 0x00004e1c, + 0x00004e55, 0x00004e85, 0x00004f11, 0x00004f69, + 0x00004f95, 0x00004fb3, 0x00004fe9, 0x00005033, + 0x00005084, 0x000050a1, 0x000050d7, 0x00005152, + 0x00005188, 0x00005196, 0x000051ab, 0x000051c0, + 0x000051d6, 0x0000522f, 0x0000523f, 0x00005244, // Entry 240 - 25F - 0x00005274, 0x0000527f, 0x0000529e, 0x000052c8, - 0x000052d0, 0x000052d5, 0x000052de, 0x000052e6, - 0x000052f2, 0x000052f8, 0x00005308, 0x00005317, - 0x0000532e, 0x0000533d, 0x00005349, 0x0000535a, - 0x00005370, 0x00005377, 0x00005384, 0x00005390, - 0x00005396, 0x0000539b, 0x000053ac, 0x000053b0, - 0x000053b6, 0x000053c5, 0x000053f6, 0x0000540f, - 0x00005428, 0x00005434, 0x0000543d, 0x00005447, + 0x00005261, 0x0000528b, 0x00005296, 0x000052b5, + 0x000052df, 0x000052e7, 0x000052ec, 0x000052f5, + 0x000052fd, 0x00005309, 0x0000530f, 0x0000531f, + 0x0000532e, 0x00005345, 0x00005354, 0x00005360, + 0x00005371, 0x00005387, 0x0000538e, 0x0000539b, + 0x000053a7, 0x000053ad, 0x000053b2, 0x000053c3, + 0x000053c7, 0x000053cd, 0x000053dc, 0x0000540d, + 0x00005426, 0x0000543f, 0x0000544b, 0x00005454, // Entry 260 - 27F - 0x00005458, 0x00005460, 0x0000546f, 0x0000547d, - 0x00005482, 0x0000548e, 0x0000549d, 0x000054b5, - 0x000054c1, 0x000054e1, 0x000054ef, 0x000054fa, - 0x0000550d, 0x00005519, 0x00005534, 0x0000555d, - 0x0000556e, 0x00005574, 0x0000557e, 0x0000559e, - 0x000055bb, 0x000055cf, 0x000055d3, 0x000055e6, - 0x000055fd, 0x00005620, 0x0000565d, 0x00005676, - 0x000056b0, 0x000056e5, 0x0000572e, 0x00005758, + 0x0000545e, 0x0000546f, 0x00005477, 0x00005486, + 0x00005494, 0x00005499, 0x000054a5, 0x000054b4, + 0x000054cc, 0x000054d8, 0x000054f8, 0x00005506, + 0x00005511, 0x00005524, 0x00005530, 0x0000554b, + 0x00005574, 0x00005585, 0x0000558b, 0x00005595, + 0x000055b5, 0x000055d2, 0x000055e6, 0x000055ea, + 0x000055fd, 0x00005614, 0x00005637, 0x00005674, + 0x0000568d, 0x000056c7, 0x000056fc, 0x00005745, // Entry 280 - 29F - 0x000057bb, 0x000057cc, 0x00005826, 0x00005838, - 0x00005855, 0x00005878, 0x00005897, 0x000058bb, - 0x000058df, 0x000058fb, 0x00005913, 0x00005927, - 0x0000593f, 0x00005957, 0x0000596d, 0x00005991, - 0x000059a2, 0x000059c8, 0x00005a17, 0x00005a2d, - 0x00005a38, 0x00005a49, 0x00005a5a, 0x00005a68, - 0x00005a74, 0x00005a98, 0x00005aae, 0x00005ad0, - 0x00005ae4, 0x00005b04, 0x00005b20, 0x00005b47, + 0x0000576f, 0x000057d2, 0x000057e3, 0x0000583d, + 0x0000584f, 0x0000586c, 0x0000588f, 0x000058ae, + 0x000058d2, 0x000058f6, 0x00005912, 0x0000592a, + 0x0000593e, 0x00005956, 0x0000596e, 0x00005984, + 0x000059a8, 0x000059b9, 0x000059df, 0x00005a2e, + 0x00005a44, 0x00005a4f, 0x00005a60, 0x00005a71, + 0x00005a7f, 0x00005a8b, 0x00005aaf, 0x00005ac5, + 0x00005ae7, 0x00005afb, 0x00005b1b, 0x00005b37, // Entry 2A0 - 2BF - 0x00005b64, 0x00005b91, 0x00005bca, 0x00005bd6, - 0x00005c0f, 0x00005c40, 0x00005c4d, 0x00005c62, - 0x00005c84, 0x00005cb2, 0x00005d29, 0x00005d8b, - 0x00005dbf, 0x00005dda, 0x00005df7, 0x00005e14, - 0x00005e41, 0x00005e5e, 0x00005e83, 0x00005ea3, - 0x00005ec7, 0x00005edf, 0x00005f06, 0x00005f2e, - 0x00005f41, -} // Size: 2812 bytes + 0x00005b5e, 0x00005b7b, 0x00005ba8, 0x00005be1, + 0x00005bed, 0x00005c26, 0x00005c57, 0x00005c64, + 0x00005c79, 0x00005c9b, 0x00005cc9, 0x00005d40, + 0x00005da2, 0x00005dd6, 0x00005df1, 0x00005e0e, + 0x00005e2b, 0x00005e58, 0x00005e75, 0x00005e9a, + 0x00005eba, 0x00005ede, 0x00005ef6, 0x00005f1d, + 0x00005f45, 0x00005f58, +} // Size: 2816 bytes -const esData string = "" + // Size: 24385 bytes +const esData string = "" + // Size: 24408 bytes "\x02Página Restringida\x02Esta función solo está permitida para usuarios" + " de pago. Por favor actualice su plan\x02Continuar para actualizar plan" + "\x02Marcadores sociales más compartir enlaces, acortar y listar, todo en" + @@ -1601,226 +1602,226 @@ const esData string = "" + // Size: 24385 bytes "uedes crear más de 5 códigos qr por lista\x02Link Corto No Encontrado" + "\x02No puedes crear más de 5 código qr por dominio\x02Código QR No Encon" + "trado\x02El usuario sigue a %[1]s\x02Este usuario no sigue a esta organi" + - "zación\x02El usuario no sigue a %[1]s\x02orgType Inválido\x02Valor de ni" + - "vel inválido\x02Valor de estado inválido\x02Un Slug válido de Organizaci" + - "ón es requerido\x02Slug de Organización es requerida para dominios de n" + - "ivel de usuario\x04\x00\x01 \x0d\x02ID inválido\x02El dominio está en us" + - "o. No se puede cambiar el servicio.\x02Nombre es requerido\x02Email es r" + - "equerido\x02Invitación de Registro\x02Linktaco: Invitación de Registro" + - "\x02Has sido invitado por %[1]s para unirse a Link Taco\x02Por favor de " + - "click en el siguiente link\x02No es posible enviar ambos cursores after " + - "y before\x02No encontrado\x02BaseURL no encontrada\x02Tipo de nube de et" + - "iquetas inválido sin el identificador de la organización\x02Solo los mie" + - "mbros con permiso de lectura pueden realizar esta acción\x02No fue posib" + - "le una organización adecuada\x02Solo los superusuarios pueden obtener do" + - "minios de nivel de sistema\x02Link Corto No Encontrado\x02Tipo de código" + - " inválido\x02El slug de organización es requerido para este tipo de toke" + - "n\x02Acceso Restringido\x02Acceso denegado.\x02Organización no encontrad" + - "a.\x02ID de listado inválido proporcionado.\x02Listado inválido para la " + - "organización especificada.\x02Zona de pruebas de GraphQL\x02Envíar Consu" + - "lta\x02Regresar a Inicio\x02Fuente de origen inválida para el importador" + - ".\x02El archivo es requerido\x02El archivo subido para esta fuente deber" + - "ía de ser html\x02El archivo subido para esta fuente debe de ser json" + - "\x02Tokens de Acceso Personal\x02Comentario\x02Creado\x02Expirado\x02Rev" + - "ocar\x02No has creado ningún token de acceso personal para tu cuenta\x02" + - "Clientes Autorizados\x02Nombre de Cliente\x02Permiso\x02No has autorizar" + - "do ningún client de tercero para acceder a tu cuenta.\x02Agregar Token d" + - "e Acceso Personal\x02Nota: Tu token de acceso nunca se te volver" + - "á a mostrar. Guárdalo en secreto. Expirará dentro de un año." + - "\x02Revocar Token de Acceso Personal\x02¿Desea revokar este token de acc" + - "eso persona? Esta acción no puede ser deshecha.\x02Si, hazlo\x02No\x02Ac" + - "ceso personal agregada con éxito\x02Token de autorización revocado con é" + - "xito\x02Clientes\x02ID de Cliente\x02Manejar\x02Agregar\x02Sin Clientes" + - "\x02Agregar Cliente OAuth2\x02Descripción de Cliente\x02URL de redirecci" + - "onamiento\x02URL de Cliente\x02Client Secreto\x02Nota: Tu cliente secret" + - "o nunca será mostrado de nuevo.\x02Manejar clientes de OAuth 2.0\x02Revo" + - "ca tokens de cliente secreto\x02Si los tokens de portador de OAuth 2.0 e" + - "mitidos para tu cliente de OAuth o tu cliente secreto se han revelado a " + - "un tercero, debes revocar todos los tokens y solicitar que se emitan ree" + - "mplazos.\x02Revocar cliente de tokens\x02Desregistrar este client OAuth" + - "\x02Esto registrará de manera permanente tu client de OAuth 2.0\x02revoc" + - "a todos los tokens emitidos, y prohíbie la emisión de nuevos tokens.\x02" + - "Desregistrar\x02Descripción\x02URL informativa\x02Cliente de OAuth 2.0 r" + - "egistrado\x02Cliente agregado con éxito\x02Cliente revocado con éxito" + - "\x02Cliente recreado con éxito\x02Autorizar\x02gustaría acceder a tu cue" + - "nta de Link Taco\x02es una applicación de terceros operada por\x02Podrás" + - " revocar este acceso en cualquier momento en la tab OAtuh de tu perfíl." + - "\x02Alcance\x02Aprobar\x02Rechazar\x02LinkTaco - La importación de tus m" + - "arcadores está completa.\x02Hola,\x02Solo queríamos informarte que la im" + - "portación de tus marcadores se ha completado con éxito.\x02- Equipo de L" + - "inkTaco\x02Dominio Inactivo\x02El dominio %[1]s está actualmente desacti" + - "vado\x02Por favor actualice la subscripción de su cuenta para reactivarl" + - "a\x02Precios\x02Cada cuenta puede crear organizaciones ilimitadas. Cada " + - "organización tiene sus propios marcadores, listados, análisis, etc. Toda" + - "s las características a continuación pertenecen a cada organización con " + - "sus propias URL únicas, agrupaciones, y más.\x02Funcionalidad\x02Gratis" + - "\x02Personal\x02Negocio\x02Precio\x02por año\x02por mes\x02meses\x02Ilim" + - "itado\x02Solo público\x02Pruébalo GRATIS\x02Marcadores\x02Guardar enlace" + - "s públicos/privados\x02Guardar notas públicas/privadas\x02Seguir otras o" + - "rganizaciones (social)\x02Organizar por etiquetas\x02Filtrado/ búsqueda " + - "avanzada\x02Fuentes RSS completas\x02Dominio personalizado + SSL\x02List" + - "ados de enlaces\x02Crear listados de enlaces (por ejemplo, biografías en" + - " redes sociales, etc.)\x02Organizar listados por etiquetas\x02Filtrar/Bu" + - "scar listados\x02Códigos QR ilimitados por listado\x02Análisis completo" + - "\x02Listado\x02Acortamiento de enlaces\x02Enlaces cortos ilimitados\x02O" + - "rganizar enlaces cortos por etiquetas\x02Filtrar/Buscar enlaces cortos" + - "\x02Códigos QR ilimitados por enlace corto\x02Historial completo de anál" + - "isis\x02Análisis específicos de códigos QR\x02Análisis de clics\x02Análi" + - "sis de referidos\x02Análisis por país\x02Análisis por ciudad\x02Análisis" + - " de dispositivos\x02Colaboración / Integraciones\x02Agregar miembros ili" + - "mitados a la organización\x02Integración con Slack\x02Integración con Ma" + - "tterMost\x02Construye tu propia integración\x02Importar / Exportar\x02Im" + - "portar desde Pinboard\x02Importar desde Firefox\x02Importar desde Chrome" + - "\x02Importar desde Safari\x02Exportar en JSON o HTML\x02Impulsado por AP" + - "I\x02Acceso completo a la API GraphQL\x02Soporte OAuth2\x02Alojamiento p" + - "ropio\x02Totalmente de código abierto\x02Hospeda tu propia versión de Li" + - "nk Taco\x02Documentación\x02Detalles de precios y características para L" + - "inkTaco.com\x02precios, enlaces, linktaco, características, planes, plan" + - "es de precios\x02¡Bienvenido a LinkTaco!\x02Aquí puedes combinar todas t" + - "us necesidades de guardar y compartir enlaces en un solo paquete compact" + - "o. Como un taco. Un taco de enlaces, por así decirlo.\x02LinkTaco es una" + - " plataforma de código abierto donde puedes alojar todos tus enlaces. Dom" + - "inios personalizados, códigos QR, análisis, API completa, múltiples orga" + - "nizaciones con miembros ilimitados son solo algunas de las característic" + - "as incluidas.\x02Los marcadores sociales no son nuevos, solo se han olvi" + - "dado. El acortamiento de enlaces con análisis ha existido siempre. Los l" + - "istados de enlaces se volvieron populares cuando las redes sociales come" + - "nzaron a permitirnos publicar un enlace a nuestros sitios web en nuestro" + - "s perfiles.\x02Hasta ahora, todas estas cosas se alojaban en diferentes " + - "servicios.\x02Marcadores sociales: Pinboard (Delicious)\x02Acortamiento " + - "de enlaces: Bitly y otros\x02Listados de enlaces: Linktree y otros\x02Ad" + - "iós Pinboard. Adiós Bitly. Adiós Linktree. ¡Hola LinkTaco!\x02Como somos" + - " un\x02proyecto 100% de código abierto\x04\x01 \x00\\\x02puedes alojar t" + - "u propia instancia si deseas tener control total sobre tu propia platafo" + - "rma.\x02Consulta la documentación de instalación para más información." + - "\x02¿Listo para comenzar? Es gratis crear una cuenta y usarla para siemp" + - "re (con algunas limitaciones). Para usar todas las funciones, solo tiene" + - "s que pagar unos pocos dólares al año, o unos pocos al mes si eres una e" + - "mpresa, y eso es todo. ¡Simple!\x02Explorar funcciones\x02Organizar marc" + - "adores\x02Lista de Links\x02Colaboración\x02Integraciones\x02Importar Ex" + - "portar\x02Listados de enlaces ilimitados (para biografías en redes socia" + - "les, etc.)\x02Los miembros pueden agregar/editar/eliminar enlaces (si se" + - " permite)\x02Los miembros tienen acceso según los permisos otorgados\x02" + - "Widget de marcadores del navegador\x02Lista de Dominio\x02Eliminar\x02Bú" + - "squeda de Nombre\x02Servicio\x02para\x02Link Cortos\x02Sin Dominios\x02C" + - "rear Dominio\x02Migrar Links Cortos\x02Los links viejos no funcionanrán." + - " Todos los códigos serán movidos al nuevo dominio.\x02Dominio creado con" + - " éxito\x02Eliminar Dominio\x02%[1]s\x02Dominio elminado con éxito\x02Si" + - "\x02Desea eliminar este dominio\x02Tus Organizaciones\x02Código Abierto" + - "\x02Patrocinado\x02Pagado\x02Activado\x02Desactivado\x02Manejar Subscrip" + - "ción\x02Dominios\x02Manejar Miembros\x02Exportar\x02Importar\x02Historia" + - "l de Pagos\x02Crear Organización\x02Nombre de usuario de Organización" + - "\x02Visibilidad predeterminada de marcadores\x02Lo sentimos, has alcanza" + - "do el número de cuentas gratuitas disponibles. Por favor actualice su cu" + - "enta gratuita para crear más\x02Público\x02Privado\x02Organización cread" + - "a con éxito\x02Actualizar Organización\x02Está habilitado\x02Organizació" + - "n actualizada con éxito\x02Agregar Miembro\x02Permiso\x02Por favor actua" + - "lice a cuenta de negocio para agregar miembros\x02Leer\x02Escribir\x02Es" + - "critura de administrador\x02Una invitación fue enviada a este usuario" + - "\x02Algo salió mal, imposible enviar invitación\x02Eliminar miembro de l" + - "a organización\x02Algo salió mal. No se pudo eliminar a este miembro: %[" + - "1]s\x02Miembro eliminado con éxito\x02¿Eliminar al miembro %[1]s (%[2]s)" + - " de la Organización %[3]s?\x02Miembro agregado con éxito\x02Algo salió m" + - "al. Imposible obtener los datos de miembros\x02Lista de Miembros\x02Sin " + - "miembros\x02Crear Enlace\x02Título\x02Visibilidad\x02Sin leer\x02Destaca" + - "do\x02Etiquetas\x02Usa comas para separar las etiquetas. Ejemplo: etique" + - "ta 1, etiqueta 2, etiqueta 3\x02URL de archivo\x02Un link fue creado con" + - " éxito\x02Error consultando url refererida: No encontrada\x02Error consu" + - "ltando link referido: %[1]v\x02marcador\x02Marcadores Populares\x02Esto " + - "no es un concurso de popularidad o algo parecido, pero es raro que no ha" + - "yan links!\x02Enlaces más populares en LinkTaco.com\x02populares, enlace" + - "s, linktaco, características, planes, planes de precios\x02Links Popular" + - "es\x02Siguiendo\x02Dejar de seguir\x02Sin organizaciones\x02Feed\x02Por" + - "\x02Buscar\x02Tu feed está vacío :( Sigue a algunas personas. Prueba los" + - " feeds Populares o Recientes para encontrar gente interesante a seguir." + - "\x02Búsqueda Avanzada\x02Incluir Tags\x02Excluir Tags\x02Limpiar\x02Sigu" + - "iendo\x02Marcadores Guardados\x02Este feed no tiene enlaces. ¡Buuu!\x02M" + - "arcadores recientes para la URL %[1]s añadidos en LinkTaco.com\x02recien" + - "tes, públicos, enlaces, linktaco\x02guardado\x02Marcadores Recientes\x02" + - "Todos\x02Sin etiquetar\x02Marcar como leído\x02Marcar como no leído\x02D" + - "estacar\x02No destacar\x02Archivar\x02Seguir\x02más nuevo\x02más vieja" + - "\x02Enlaces públicos recientes añadidos a %[1]s en LinkTaco.com\x02Enlac" + - "es públicos recientes añadidos a LinkTaco.com\x02Links Recientes\x02%[1]" + - "s Enlaces\x02Tienes %[1]d enlaces restrigidos guardados.\x02Actualiza la" + - " organización para activarlos.\x02Detalle de Enlace\x02Publicación Públi" + - "ca\x02Públicación Privada\x02Marcador '%[1]s' en LinkTaco.com\x02marcado" + - "r, nota, detalle, popular, enlaces, linktaco\x02Borrar Marcador\x02Algo " + - "salió mal. No se pudo eliminar este marcador.\x02Marcador eliminado con " + - "éxito\x02¿Realmente deseas eliminar este marcador?\x02Actualizar Enlace" + - "\x02Desea eliminar\x02Link actualizado con éxito\x02Código QR por Link T" + - "aco!\x02Serás redireccionado en 10 segundos.\x02Detalles de Código QR" + - "\x02Bajar Imágen\x02Elimiar Código QR\x02Algo salió mal. El Código QE no" + - " pudo ser eliminado.\x02Código QR elminado con éxito\x02Desea eliminar e" + - "ste código qr\x02Exportar Datos\x02Formato de archivo\x02Esta función no" + - " está habilitada para cuentas gratuitas. Por favor actualizar\x02Como ad" + - "ministrador de sistema corrar el siguiente comando en el canal que desee" + - "s conectar\x02Desconectar\x02Conectar\x02Conectado\x02Importar Datos\x02" + - "Fuente\x02Click en Manejar Marcadores desde el menú de Marcadores\x02Una" + - " nueva ventana llamada Biblioteca se abrirá\x02En la barra lateral izqui" + - "erda seleccione la carpeta que desea exportar. Para exportar todos los m" + - "arcadores selecciones Todos los Marcadores\x02Click en el ícono con dos " + - "flechas (arriba y abajo) y escoje 'Exportar Marcador a HTML'\x02En el me" + - "nú de Archivo selecciones Exportar\x02Selecione Exportar Marcadores\x02V" + - "e al menú de Marcadores y escoge Manejar Marcadores\x02En la barra latar" + - "eral izquierda selecciones la carpeta que desea exportar\x02En la barra " + - "marcadores, de click en los tres puntos de la parte superior derecha\x02" + - "Click en Exportar Marcadores\x02Visita https://pinboard.in/export/ y da " + - "click en JSON\x02Al importar a una cuenta/organización gratuita, todos l" + - "os marcadores privados del tablero se marcarán como restringidos.\x02Act" + - "ualice su cuenta para admitir marcadores privados.\x02Instrucciones\x02M" + - "arcadores de Safari\x02Marcadores de Chrome\x02Marcadores de Firefox\x02" + - "Se está procesando la importación de tu marcador. Te notificaremos cuand" + - "o se complete.\x02Actualizar Nota\x02Nota\x02Nota '%[1]s' en LinkTaco.co" + - "m\x02nota, detalle, popular, enlaces, linktaco\x02Crear Nota\x02Una nota" + - " fue creada con éxito\x02Error consultado nota referenciada: %[1]v\x02Ta" + - "blero\x02Tour\x02Reciente\x02Popular\x02Categorías\x02Sobre\x02Iniciar S" + - "esión\x02Cerrar Sesión\x02Zona de pruebas de GQL\x02Guardar Enlace\x02Gu" + - "ardar Noa\x02Token Personales\x02Aplicaciones Clientes\x02Listas\x02Link" + - "s Cortos\x02Administrar\x02Ayuda\x02Blog\x02Actualizar Links\x02URL\x02O" + - "rden\x02Eliminar Lista\x02Algo salió mal. El enlace no pudo ser eliminad" + - "o\x02Enlace creado con éxito\x02Desea eliminar este link\x02Crear Links" + - "\x02Anterior\x02Sin Links\x02Actualizar Lista\x02Dominio\x02Es por defec" + - "to\x02Eliminar Foto\x02Otro\x02Otro Nombre\x02Links Sociales\x02Lista cr" + - "eada con éxito\x02Crear Lista\x02Una lista fue creada con éxito\x02Manej" + - "ar Links\x02Sin Listas\x02Fecha de Creación\x02Códigos QR\x02Lista elimi" + - "nada con éxito\x02¿Realmente quieres eliminar esta lista?\x02Crear Códig" + - "o QR\x02Crear\x02Descargar\x02Fondo de pantalla personalizado\x02Código " + - "QR creado con éxito\x02Código QR de Lista\x02Ver\x02No hay Códigos QR" + - "\x02Desconectar Mattermost\x02Mattermost desconectado con éxito\x02Desea" + - " realmente desconectar esta organización de mattermost\x02Connectar con " + - "Mattermost\x02Este equipo ya se encuentra vinculado a una organización" + - "\x02¿Deseas conectar esta organización con mattermost?\x02Esta función e" + - "stá restringida para cuentas gratis. Por favor actualiza\x02La organizac" + - "ión fue vinculada con éxito\x02Lo sentimos, las cuentas gratuitas no sop" + - "ortan la integración con Mattermost. Por favor actualice\x02Conectar Usu" + - "ario\x02Para interactuar con mattermost tienes que conectar tu cuenta co" + - "n tu usuario de Link Taco\x02¿Desea proceder?\x02Usuario conectado con é" + - "xito\x02Connexión con slack no encontrada\x02Te enviamos un mensaje priv" + - "ado\x02El texto a ser buscado es requerido\x02No se encuentraron links p" + - "ara %[1]s\x02Organización no encontrada\x02El título es requerido\x02La " + - "url es requerida\x02El código es requerido\x02El dominio es requerido" + - "\x02Dominio no encontrado\x02A nuevo short fue creado con éxito\x02Url e" + - "s requerida\x02Un nuevo enlace fue creado con éxito\x02Por favor haga cl" + - "ick en el próximo link para vincular una organización %[1]s\x02Instalacc" + - "ión exitosa\x02Link Corto\x02Sin Links Cortos\x02Crear Link Corto\x02Cód" + - "igo Corto\x02Sin Dominio\x02Un link corto fue creado con éxito\x02Actual" + - "izar Link Corto\x02Link Corto actualizado con éxito\x02Eliminar Link Cor" + - "to\x02Link Corto eliminado con éxito\x02URL acortada por Link Taco!\x02N" + - "o se proporcionó un argumento de URL\x02%[1]s: dominio no encontrado\x02" + - "Tu enlace corto fue creado con éxito: %[1]s\x02Tu enlace fue guardado co" + - "n éxito. Detalles aquí: %[1]s\x02Buscar Link\x02Por favor vincule tu usu" + - "ario de slack con el link: %[1]s\x02Te enviamos un mensaje directo con i" + - "nstrucciones\x02Agregar Link\x02Desconectar de Slack\x02Slack fue descon" + - "ectado con éxito\x02Desea desconectar esta organización de slack\x02Lo s" + - "entimos, las cuentas gratis no soportan integración con Slack. Por favor" + - " actualice su subscripcón para continuar\x02Para interactuar con Link Ta" + - "co tienes que conectar tu cuenta de slack con tu usuario de Link Taco" + - "\x02Algo salió mal. El usuario no puede ser vinculado.\x02Conectar a Sla" + - "ck Workspace\x02Respuesta de slack inválida\x02¿Deseas conectar con Slac" + - "k?\x02Organización vinculada con éxito con slack\x02Email y/o password i" + - "nválido\x02Las nuevas contraseñas no coinciden\x02El usuario no está aut" + - "enticado\x02La contraseña actual es incorrecta\x02Este campo es requerid" + - "o\x02Por favor introduzca un correo válido\x02Por favor introduzca un nú" + - "mero válido\x02El '%[1]s' falló." + "zación\x02El usuario no sigue a %[1]s\x02orgType Inválido\x02Visibilidad" + + " no válida\x02Valor de nivel inválido\x02Valor de estado inválido\x02Un " + + "Slug válido de Organización es requerido\x02Slug de Organización es requ" + + "erida para dominios de nivel de usuario\x04\x00\x01 \x0d\x02ID inválido" + + "\x02El dominio está en uso. No se puede cambiar el servicio.\x02Nombre e" + + "s requerido\x02Email es requerido\x02Invitación de Registro\x02Linktaco:" + + " Invitación de Registro\x02Has sido invitado por %[1]s para unirse a Lin" + + "k Taco\x02Por favor de click en el siguiente link\x02No es posible envia" + + "r ambos cursores after y before\x02No encontrado\x02BaseURL no encontrad" + + "a\x02Tipo de nube de etiquetas inválido sin el identificador de la organ" + + "ización\x02Solo los miembros con permiso de lectura pueden realizar esta" + + " acción\x02No fue posible una organización adecuada\x02Solo los superusu" + + "arios pueden obtener dominios de nivel de sistema\x02Link Corto No Encon" + + "trado\x02Tipo de código inválido\x02El slug de organización es requerido" + + " para este tipo de token\x02Acceso Restringido\x02Acceso denegado.\x02Or" + + "ganización no encontrada.\x02ID de listado inválido proporcionado.\x02Li" + + "stado inválido para la organización especificada.\x02Zona de pruebas de " + + "GraphQL\x02Envíar Consulta\x02Regresar a Inicio\x02Fuente de origen invá" + + "lida para el importador.\x02El archivo es requerido\x02El archivo subido" + + " para esta fuente debería de ser html\x02El archivo subido para esta fue" + + "nte debe de ser json\x02Tokens de Acceso Personal\x02Comentario\x02Cread" + + "o\x02Expirado\x02Revocar\x02No has creado ningún token de acceso persona" + + "l para tu cuenta\x02Clientes Autorizados\x02Nombre de Cliente\x02Permiso" + + "\x02No has autorizardo ningún client de tercero para acceder a tu cuenta" + + ".\x02Agregar Token de Acceso Personal\x02Nota: Tu token de acceso nunca se te volverá a mostrar. Guárdalo en secreto. Expirará " + + "dentro de un año.\x02Revocar Token de Acceso Personal\x02¿Desea revokar " + + "este token de acceso persona? Esta acción no puede ser deshecha.\x02Si, " + + "hazlo\x02No\x02Acceso personal agregada con éxito\x02Token de autorizaci" + + "ón revocado con éxito\x02Clientes\x02ID de Cliente\x02Manejar\x02Agrega" + + "r\x02Sin Clientes\x02Agregar Cliente OAuth2\x02Descripción de Cliente" + + "\x02URL de redireccionamiento\x02URL de Cliente\x02Client Secreto\x02Not" + + "a: Tu cliente secreto nunca será mostrado de nuevo.\x02Manejar clientes " + + "de OAuth 2.0\x02Revoca tokens de cliente secreto\x02Si los tokens de por" + + "tador de OAuth 2.0 emitidos para tu cliente de OAuth o tu cliente secret" + + "o se han revelado a un tercero, debes revocar todos los tokens y solicit" + + "ar que se emitan reemplazos.\x02Revocar cliente de tokens\x02Desregistra" + + "r este client OAuth\x02Esto registrará de manera permanente tu client de" + + " OAuth 2.0\x02revoca todos los tokens emitidos, y prohíbie la emisión de" + + " nuevos tokens.\x02Desregistrar\x02Descripción\x02URL informativa\x02Cli" + + "ente de OAuth 2.0 registrado\x02Cliente agregado con éxito\x02Cliente re" + + "vocado con éxito\x02Cliente recreado con éxito\x02Autorizar\x02gustaría " + + "acceder a tu cuenta de Link Taco\x02es una applicación de terceros opera" + + "da por\x02Podrás revocar este acceso en cualquier momento en la tab OAtu" + + "h de tu perfíl.\x02Alcance\x02Aprobar\x02Rechazar\x02LinkTaco - La impor" + + "tación de tus marcadores está completa.\x02Hola,\x02Solo queríamos infor" + + "marte que la importación de tus marcadores se ha completado con éxito." + + "\x02- Equipo de LinkTaco\x02Dominio Inactivo\x02El dominio %[1]s está ac" + + "tualmente desactivado\x02Por favor actualice la subscripción de su cuent" + + "a para reactivarla\x02Precios\x02Cada cuenta puede crear organizaciones " + + "ilimitadas. Cada organización tiene sus propios marcadores, listados, an" + + "álisis, etc. Todas las características a continuación pertenecen a cada" + + " organización con sus propias URL únicas, agrupaciones, y más.\x02Funcio" + + "nalidad\x02Gratis\x02Personal\x02Negocio\x02Precio\x02por año\x02por mes" + + "\x02meses\x02Ilimitado\x02Solo público\x02Pruébalo GRATIS\x02Marcadores" + + "\x02Guardar enlaces públicos/privados\x02Guardar notas públicas/privadas" + + "\x02Seguir otras organizaciones (social)\x02Organizar por etiquetas\x02F" + + "iltrado/ búsqueda avanzada\x02Fuentes RSS completas\x02Dominio personali" + + "zado + SSL\x02Listados de enlaces\x02Crear listados de enlaces (por ejem" + + "plo, biografías en redes sociales, etc.)\x02Organizar listados por etiqu" + + "etas\x02Filtrar/Buscar listados\x02Códigos QR ilimitados por listado\x02" + + "Análisis completo\x02Listado\x02Acortamiento de enlaces\x02Enlaces corto" + + "s ilimitados\x02Organizar enlaces cortos por etiquetas\x02Filtrar/Buscar" + + " enlaces cortos\x02Códigos QR ilimitados por enlace corto\x02Historial c" + + "ompleto de análisis\x02Análisis específicos de códigos QR\x02Análisis de" + + " clics\x02Análisis de referidos\x02Análisis por país\x02Análisis por ciu" + + "dad\x02Análisis de dispositivos\x02Colaboración / Integraciones\x02Agreg" + + "ar miembros ilimitados a la organización\x02Integración con Slack\x02Int" + + "egración con MatterMost\x02Construye tu propia integración\x02Importar /" + + " Exportar\x02Importar desde Pinboard\x02Importar desde Firefox\x02Import" + + "ar desde Chrome\x02Importar desde Safari\x02Exportar en JSON o HTML\x02I" + + "mpulsado por API\x02Acceso completo a la API GraphQL\x02Soporte OAuth2" + + "\x02Alojamiento propio\x02Totalmente de código abierto\x02Hospeda tu pro" + + "pia versión de Link Taco\x02Documentación\x02Detalles de precios y carac" + + "terísticas para LinkTaco.com\x02precios, enlaces, linktaco, característi" + + "cas, planes, planes de precios\x02¡Bienvenido a LinkTaco!\x02Aquí puedes" + + " combinar todas tus necesidades de guardar y compartir enlaces en un sol" + + "o paquete compacto. Como un taco. Un taco de enlaces, por así decirlo." + + "\x02LinkTaco es una plataforma de código abierto donde puedes alojar tod" + + "os tus enlaces. Dominios personalizados, códigos QR, análisis, API compl" + + "eta, múltiples organizaciones con miembros ilimitados son solo algunas d" + + "e las características incluidas.\x02Los marcadores sociales no son nuevo" + + "s, solo se han olvidado. El acortamiento de enlaces con análisis ha exis" + + "tido siempre. Los listados de enlaces se volvieron populares cuando las " + + "redes sociales comenzaron a permitirnos publicar un enlace a nuestros si" + + "tios web en nuestros perfiles.\x02Hasta ahora, todas estas cosas se aloj" + + "aban en diferentes servicios.\x02Marcadores sociales: Pinboard (Deliciou" + + "s)\x02Acortamiento de enlaces: Bitly y otros\x02Listados de enlaces: Lin" + + "ktree y otros\x02Adiós Pinboard. Adiós Bitly. Adiós Linktree. ¡Hola Link" + + "Taco!\x02Como somos un\x02proyecto 100% de código abierto\x04\x01 \x00\\" + + "\x02puedes alojar tu propia instancia si deseas tener control total sobr" + + "e tu propia plataforma.\x02Consulta la documentación de instalación para" + + " más información.\x02¿Listo para comenzar? Es gratis crear una cuenta y " + + "usarla para siempre (con algunas limitaciones). Para usar todas las func" + + "iones, solo tienes que pagar unos pocos dólares al año, o unos pocos al " + + "mes si eres una empresa, y eso es todo. ¡Simple!\x02Explorar funcciones" + + "\x02Organizar marcadores\x02Lista de Links\x02Colaboración\x02Integracio" + + "nes\x02Importar Exportar\x02Listados de enlaces ilimitados (para biograf" + + "ías en redes sociales, etc.)\x02Los miembros pueden agregar/editar/elim" + + "inar enlaces (si se permite)\x02Los miembros tienen acceso según los per" + + "misos otorgados\x02Widget de marcadores del navegador\x02Lista de Domini" + + "o\x02Eliminar\x02Búsqueda de Nombre\x02Servicio\x02para\x02Link Cortos" + + "\x02Sin Dominios\x02Crear Dominio\x02Migrar Links Cortos\x02Los links vi" + + "ejos no funcionanrán. Todos los códigos serán movidos al nuevo dominio." + + "\x02Dominio creado con éxito\x02Eliminar Dominio\x02%[1]s\x02Dominio elm" + + "inado con éxito\x02Si\x02Desea eliminar este dominio\x02Tus Organizacion" + + "es\x02Código Abierto\x02Patrocinado\x02Pagado\x02Activado\x02Desactivado" + + "\x02Manejar Subscripción\x02Dominios\x02Manejar Miembros\x02Exportar\x02" + + "Importar\x02Historial de Pagos\x02Crear Organización\x02Nombre de usuari" + + "o de Organización\x02Visibilidad predeterminada de marcadores\x02Lo sent" + + "imos, has alcanzado el número de cuentas gratuitas disponibles. Por favo" + + "r actualice su cuenta gratuita para crear más\x02Público\x02Privado\x02O" + + "rganización creada con éxito\x02Actualizar Organización\x02Está habilita" + + "do\x02Organización actualizada con éxito\x02Agregar Miembro\x02Permiso" + + "\x02Por favor actualice a cuenta de negocio para agregar miembros\x02Lee" + + "r\x02Escribir\x02Escritura de administrador\x02Una invitación fue enviad" + + "a a este usuario\x02Algo salió mal, imposible enviar invitación\x02Elimi" + + "nar miembro de la organización\x02Algo salió mal. No se pudo eliminar a " + + "este miembro: %[1]s\x02Miembro eliminado con éxito\x02¿Eliminar al miemb" + + "ro %[1]s (%[2]s) de la Organización %[3]s?\x02Miembro agregado con éxito" + + "\x02Algo salió mal. Imposible obtener los datos de miembros\x02Lista de " + + "Miembros\x02Sin miembros\x02Crear Enlace\x02Título\x02Visibilidad\x02Sin" + + " leer\x02Destacado\x02Etiquetas\x02Usa comas para separar las etiquetas." + + " Ejemplo: etiqueta 1, etiqueta 2, etiqueta 3\x02URL de archivo\x02Un lin" + + "k fue creado con éxito\x02Error consultando url refererida: No encontrad" + + "a\x02Error consultando link referido: %[1]v\x02marcador\x02Marcadores Po" + + "pulares\x02Esto no es un concurso de popularidad o algo parecido, pero e" + + "s raro que no hayan links!\x02Enlaces más populares en LinkTaco.com\x02p" + + "opulares, enlaces, linktaco, características, planes, planes de precios" + + "\x02Links Populares\x02Siguiendo\x02Dejar de seguir\x02Sin organizacione" + + "s\x02Feed\x02Por\x02Buscar\x02Tu feed está vacío :( Sigue a algunas pers" + + "onas. Prueba los feeds Populares o Recientes para encontrar gente intere" + + "sante a seguir.\x02Búsqueda Avanzada\x02Incluir Tags\x02Excluir Tags\x02" + + "Limpiar\x02Siguiendo\x02Marcadores Guardados\x02Este feed no tiene enlac" + + "es. ¡Buuu!\x02Marcadores recientes para la URL %[1]s añadidos en LinkTac" + + "o.com\x02recientes, públicos, enlaces, linktaco\x02guardado\x02Marcadore" + + "s Recientes\x02Todos\x02Sin etiquetar\x02Marcar como leído\x02Marcar com" + + "o no leído\x02Destacar\x02No destacar\x02Archivar\x02Seguir\x02más nuevo" + + "\x02más vieja\x02Enlaces públicos recientes añadidos a %[1]s en LinkTaco" + + ".com\x02Enlaces públicos recientes añadidos a LinkTaco.com\x02Links Reci" + + "entes\x02%[1]s Enlaces\x02Tienes %[1]d enlaces restrigidos guardados." + + "\x02Actualiza la organización para activarlos.\x02Detalle de Enlace\x02P" + + "ublicación Pública\x02Públicación Privada\x02Marcador '%[1]s' en LinkTac" + + "o.com\x02marcador, nota, detalle, popular, enlaces, linktaco\x02Borrar M" + + "arcador\x02Algo salió mal. No se pudo eliminar este marcador.\x02Marcado" + + "r eliminado con éxito\x02¿Realmente deseas eliminar este marcador?\x02Ac" + + "tualizar Enlace\x02Desea eliminar\x02Link actualizado con éxito\x02Códig" + + "o QR por Link Taco!\x02Serás redireccionado en 10 segundos.\x02Detalles " + + "de Código QR\x02Bajar Imágen\x02Elimiar Código QR\x02Algo salió mal. El " + + "Código QE no pudo ser eliminado.\x02Código QR elminado con éxito\x02Dese" + + "a eliminar este código qr\x02Exportar Datos\x02Formato de archivo\x02Est" + + "a función no está habilitada para cuentas gratuitas. Por favor actualiza" + + "r\x02Como administrador de sistema corrar el siguiente comando en el can" + + "al que desees conectar\x02Desconectar\x02Conectar\x02Conectado\x02Import" + + "ar Datos\x02Fuente\x02Click en Manejar Marcadores desde el menú de Marca" + + "dores\x02Una nueva ventana llamada Biblioteca se abrirá\x02En la barra l" + + "ateral izquierda seleccione la carpeta que desea exportar. Para exportar" + + " todos los marcadores selecciones Todos los Marcadores\x02Click en el íc" + + "ono con dos flechas (arriba y abajo) y escoje 'Exportar Marcador a HTML'" + + "\x02En el menú de Archivo selecciones Exportar\x02Selecione Exportar Mar" + + "cadores\x02Ve al menú de Marcadores y escoge Manejar Marcadores\x02En la" + + " barra latareral izquierda selecciones la carpeta que desea exportar\x02" + + "En la barra marcadores, de click en los tres puntos de la parte superior" + + " derecha\x02Click en Exportar Marcadores\x02Visita https://pinboard.in/e" + + "xport/ y da click en JSON\x02Al importar a una cuenta/organización gratu" + + "ita, todos los marcadores privados del tablero se marcarán como restring" + + "idos.\x02Actualice su cuenta para admitir marcadores privados.\x02Instru" + + "cciones\x02Marcadores de Safari\x02Marcadores de Chrome\x02Marcadores de" + + " Firefox\x02Se está procesando la importación de tu marcador. Te notific" + + "aremos cuando se complete.\x02Actualizar Nota\x02Nota\x02Nota '%[1]s' en" + + " LinkTaco.com\x02nota, detalle, popular, enlaces, linktaco\x02Crear Nota" + + "\x02Una nota fue creada con éxito\x02Error consultado nota referenciada:" + + " %[1]v\x02Tablero\x02Tour\x02Reciente\x02Popular\x02Categorías\x02Sobre" + + "\x02Iniciar Sesión\x02Cerrar Sesión\x02Zona de pruebas de GQL\x02Guardar" + + " Enlace\x02Guardar Noa\x02Token Personales\x02Aplicaciones Clientes\x02L" + + "istas\x02Links Cortos\x02Administrar\x02Ayuda\x02Blog\x02Actualizar Link" + + "s\x02URL\x02Orden\x02Eliminar Lista\x02Algo salió mal. El enlace no pudo" + + " ser eliminado\x02Enlace creado con éxito\x02Desea eliminar este link" + + "\x02Crear Links\x02Anterior\x02Sin Links\x02Actualizar Lista\x02Dominio" + + "\x02Es por defecto\x02Eliminar Foto\x02Otro\x02Otro Nombre\x02Links Soci" + + "ales\x02Lista creada con éxito\x02Crear Lista\x02Una lista fue creada co" + + "n éxito\x02Manejar Links\x02Sin Listas\x02Fecha de Creación\x02Códigos Q" + + "R\x02Lista eliminada con éxito\x02¿Realmente quieres eliminar esta lista" + + "?\x02Crear Código QR\x02Crear\x02Descargar\x02Fondo de pantalla personal" + + "izado\x02Código QR creado con éxito\x02Código QR de Lista\x02Ver\x02No h" + + "ay Códigos QR\x02Desconectar Mattermost\x02Mattermost desconectado con é" + + "xito\x02Desea realmente desconectar esta organización de mattermost\x02C" + + "onnectar con Mattermost\x02Este equipo ya se encuentra vinculado a una o" + + "rganización\x02¿Deseas conectar esta organización con mattermost?\x02Est" + + "a función está restringida para cuentas gratis. Por favor actualiza\x02L" + + "a organización fue vinculada con éxito\x02Lo sentimos, las cuentas gratu" + + "itas no soportan la integración con Mattermost. Por favor actualice\x02C" + + "onectar Usuario\x02Para interactuar con mattermost tienes que conectar t" + + "u cuenta con tu usuario de Link Taco\x02¿Desea proceder?\x02Usuario cone" + + "ctado con éxito\x02Connexión con slack no encontrada\x02Te enviamos un m" + + "ensaje privado\x02El texto a ser buscado es requerido\x02No se encuentra" + + "ron links para %[1]s\x02Organización no encontrada\x02El título es reque" + + "rido\x02La url es requerida\x02El código es requerido\x02El dominio es r" + + "equerido\x02Dominio no encontrado\x02A nuevo short fue creado con éxito" + + "\x02Url es requerida\x02Un nuevo enlace fue creado con éxito\x02Por favo" + + "r haga click en el próximo link para vincular una organización %[1]s\x02" + + "Instalacción exitosa\x02Link Corto\x02Sin Links Cortos\x02Crear Link Cor" + + "to\x02Código Corto\x02Sin Dominio\x02Un link corto fue creado con éxito" + + "\x02Actualizar Link Corto\x02Link Corto actualizado con éxito\x02Elimina" + + "r Link Corto\x02Link Corto eliminado con éxito\x02URL acortada por Link " + + "Taco!\x02No se proporcionó un argumento de URL\x02%[1]s: dominio no enco" + + "ntrado\x02Tu enlace corto fue creado con éxito: %[1]s\x02Tu enlace fue g" + + "uardado con éxito. Detalles aquí: %[1]s\x02Buscar Link\x02Por favor vinc" + + "ule tu usuario de slack con el link: %[1]s\x02Te enviamos un mensaje dir" + + "ecto con instrucciones\x02Agregar Link\x02Desconectar de Slack\x02Slack " + + "fue desconectado con éxito\x02Desea desconectar esta organización de sla" + + "ck\x02Lo sentimos, las cuentas gratis no soportan integración con Slack." + + " Por favor actualice su subscripcón para continuar\x02Para interactuar c" + + "on Link Taco tienes que conectar tu cuenta de slack con tu usuario de Li" + + "nk Taco\x02Algo salió mal. El usuario no puede ser vinculado.\x02Conecta" + + "r a Slack Workspace\x02Respuesta de slack inválida\x02¿Deseas conectar c" + + "on Slack?\x02Organización vinculada con éxito con slack\x02Email y/o pas" + + "sword inválido\x02Las nuevas contraseñas no coinciden\x02El usuario no e" + + "stá autenticado\x02La contraseña actual es incorrecta\x02Este campo es r" + + "equerido\x02Por favor introduzca un correo válido\x02Por favor introduzc" + + "a un número válido\x02El '%[1]s' falló." - // Total table size 50771 bytes (49KiB); checksum: 7CF3A61E + // Total table size 50821 bytes (49KiB); checksum: E315B56E diff --git a/internal/translations/locales/en/out.gotext.json b/internal/translations/locales/en/out.gotext.json index 56b9ac9..b8de371 100644 --- a/internal/translations/locales/en/out.gotext.json +++ b/internal/translations/locales/en/out.gotext.json @@ -1766,6 +1766,13 @@ "translatorComment": "Copied from source.", "fuzzy": true }, + { + "id": "Invalid visibility", + "message": "Invalid visibility", + "translation": "Invalid visibility", + "translatorComment": "Copied from source.", + "fuzzy": true + }, { "id": "Invalid level value.", "message": "Invalid level value.", diff --git a/internal/translations/locales/es/messages.gotext.json b/internal/translations/locales/es/messages.gotext.json index 6a90d4a..6910a96 100644 --- a/internal/translations/locales/es/messages.gotext.json +++ b/internal/translations/locales/es/messages.gotext.json @@ -1276,6 +1276,11 @@ "message": "Invalid orgType", "translation": "orgType Inválido" }, + { + "id": "Invalid visibility", + "message": "Invalid visibility", + "translation": "Visibilidad no válida" + }, { "id": "Invalid level value.", "message": "Invalid level value.", diff --git a/internal/translations/locales/es/out.gotext.json b/internal/translations/locales/es/out.gotext.json index 265fe76..8913dd4 100644 --- a/internal/translations/locales/es/out.gotext.json +++ b/internal/translations/locales/es/out.gotext.json @@ -1276,6 +1276,11 @@ "message": "Invalid orgType", "translation": "orgType Inválido" }, + { + "id": "Invalid visibility", + "message": "Invalid visibility", + "translation": "Visibilidad no válida" + }, { "id": "Invalid level value.", "message": "Invalid level value.", diff --git a/migrations/0007_add_base_org_visibility.down.sql b/migrations/0007_add_base_org_visibility.down.sql new file mode 100644 index 0000000..c54fb0c --- /dev/null +++ b/migrations/0007_add_base_org_visibility.down.sql @@ -0,0 +1,4 @@ +ALTER TABLE organizations DROP COLUMN visibility; +ALTER TABLE base_urls DROP COLUMN visibility; + +DROP TYPE public_visibility; diff --git a/migrations/0007_add_base_org_visibility.up.sql b/migrations/0007_add_base_org_visibility.up.sql new file mode 100644 index 0000000..83c1b2e --- /dev/null +++ b/migrations/0007_add_base_org_visibility.up.sql @@ -0,0 +1,4 @@ +CREATE TYPE public_visibility AS ENUM ('PUBLIC', 'HIDDEN'); + +ALTER TABLE organizations ADD COLUMN visibility public_visibility DEFAULT 'PUBLIC'; +ALTER TABLE base_urls ADD COLUMN visibility public_visibility DEFAULT 'PUBLIC'; diff --git a/models/base_url.go b/models/base_url.go index 18c6560..5b1b484 100644 --- a/models/base_url.go +++ b/models/base_url.go @@ -63,9 +63,11 @@ func GetBaseURLs(ctx context.Context, opts *database.FilterOptions) ([]*BaseURL, q := opts.GetBuilder(nil) rows, err := q. Columns("b.id", "b.url", "b.title", "b.counter", "b.data", "b.public_ready", "b.hash", - "b.parse_attempts", "b.last_parse_attempt", "b.created_on", "json_agg(t)::jsonb"). + "b.parse_attempts", "b.last_parse_attempt", "b.created_on", "b.visibility", + "json_agg(t)::jsonb"). From("base_urls b"). LeftJoin("org_links ol ON ol.base_url_id = b.id"). + LeftJoin("organizations o ON o.id = ol.org_id"). LeftJoin("tag_links tl ON tl.org_link_id = ol.id"). LeftJoin("tags t ON t.id = tl.tag_id"). GroupBy("b.id"). @@ -86,7 +88,7 @@ func GetBaseURLs(ctx context.Context, opts *database.FilterOptions) ([]*BaseURL, var tags string if err = rows.Scan(&url.ID, &url.URL, &url.Title, &url.Counter, &url.Data, &url.PublicReady, &url.Hash, &url.ParseAttempts, - &url.LastParseAttempt, &url.CreatedOn, &tags); err != nil { + &url.LastParseAttempt, &url.CreatedOn, &url.Visibility, &tags); err != nil { return err } @@ -124,13 +126,14 @@ func (b *BaseURL) Load(ctx context.Context) error { err := database.WithTx(ctx, database.TxOptionsRO, func(tx *sql.Tx) error { err := sq. Select("id", "title", "url", "counter", "data", "public_ready", "hash", - "parse_attempts", "last_parse_attempt", "created_on"). + "parse_attempts", "last_parse_attempt", "created_on", "visibility"). From("base_urls"). Where("id = ?", b.ID). PlaceholderFormat(database.GetPlaceholderFormat()). RunWith(tx). ScanContext(ctx, &b.ID, &b.Title, &b.URL, &b.Counter, &b.Data, - &b.PublicReady, &b.Hash, &b.ParseAttempts, &b.LastParseAttempt, &b.CreatedOn) + &b.PublicReady, &b.Hash, &b.ParseAttempts, &b.LastParseAttempt, + &b.CreatedOn, &b.Visibility) if err != nil { if err == sql.ErrNoRows { return nil @@ -178,6 +181,7 @@ func (b *BaseURL) Store(ctx context.Context) error { Set("hash", b.Hash). Set("parse_attempts", b.ParseAttempts). Set("last_parse_attempt", b.LastParseAttempt). + Set("visibility", b.Visibility). Where("id = ?", b.ID). Suffix(`RETURNING (updated_on)`). PlaceholderFormat(database.GetPlaceholderFormat()). diff --git a/models/models.go b/models/models.go index f38a5f2..147f07e 100644 --- a/models/models.go +++ b/models/models.go @@ -35,17 +35,18 @@ type User struct { // Organization is... type Organization struct { - ID int `db:"id"` - OwnerID int `db:"owner_id"` - OrgType string `db:"org_type"` - Name string `db:"name"` - Slug string `db:"slug"` - Image string `db:"image"` - Timezone string `db:"timezone"` - Settings OrganizationSettings `db:"settings"` - IsActive bool `db:"is_active"` - CreatedOn time.Time `db:"created_on"` - UpdatedOn time.Time `db:"updated_on"` + ID int `db:"id"` + OwnerID int `db:"owner_id"` + OrgType string `db:"org_type"` + Name string `db:"name"` + Slug string `db:"slug"` + Image string `db:"image"` + Timezone string `db:"timezone"` + Settings OrganizationSettings `db:"settings"` + IsActive bool `db:"is_active"` + Visibility string `db:"visibility"` + CreatedOn time.Time `db:"created_on"` + UpdatedOn time.Time `db:"updated_on"` OwnerName string `db:"-"` SlackConnID sql.NullInt64 `db:"-"` @@ -63,6 +64,7 @@ type BaseURL struct { Hash string `db:"hash" json:"hash"` ParseAttempts int `db:"parse_attempts"` LastParseAttempt sql.NullTime `db:"last_parse_attempt"` + Visibility string `db:"visibility"` CreatedOn time.Time `db:"created_on"` UpdatedOn time.Time `db:"updated_on"` diff --git a/models/organization.go b/models/organization.go index 93ca688..8bca091 100644 --- a/models/organization.go +++ b/models/organization.go @@ -37,6 +37,13 @@ const ( BillingStatusSponsored string = "SPONSORED" ) +// Visibility for organizations and base urls to hide spammer links from +// popular and recent lists +const ( + VisibilityPublic string = "PUBLIC" + VisibilityHidden string = "HIDDEN" +) + type BillingSettings struct { Status string `json:"status"` // BillingStatus } @@ -72,7 +79,7 @@ func GetOrganizations(ctx context.Context, opts *database.FilterOptions) ([]*Org q := opts.GetBuilder(nil) rows, err := q. Columns("o.id", "o.owner_id", "o.org_type", "o.name", "o.slug", "o.image", "o.timezone", - "o.settings", "o.is_active", "o.created_on", "o.updated_on", "u.full_name", "sc.id", + "o.settings", "o.is_active", "o.created_on", "o.updated_on", "o.visibility", "u.full_name", "sc.id", "mc.id"). From("organizations o"). Join("users u ON o.owner_id = u.id"). @@ -96,8 +103,9 @@ func GetOrganizations(ctx context.Context, opts *database.FilterOptions) ([]*Org for rows.Next() { var org Organization if err = rows.Scan(&org.ID, &org.OwnerID, &org.OrgType, &org.Name, &org.Slug, - &org.Image, &org.Timezone, &org.Settings, &org.IsActive, &org.CreatedOn, &org.UpdatedOn, - &org.OwnerName, &org.SlackConnID, &org.MattermostConnID, + &org.Image, &org.Timezone, &org.Settings, &org.IsActive, &org.CreatedOn, + &org.UpdatedOn, &org.Visibility, &org.OwnerName, &org.SlackConnID, + &org.MattermostConnID, ); err != nil { return err } @@ -131,14 +139,15 @@ func (o *Organization) Load(ctx context.Context) error { err := database.WithTx(ctx, database.TxOptionsRO, func(tx *sql.Tx) error { err := sq. Select("o.id", "o.owner_id", "o.org_type", "o.name", "o.slug", "o.image", "o.timezone", - "o.settings", "o.is_active", "o.created_on", "o.updated_on", "u.full_name"). + "o.settings", "o.is_active", "o.created_on", "o.updated_on", "o.visibility", + "u.full_name"). From("organizations o"). Join("users u ON o.owner_id = u.id"). Where("o.id = ?", o.ID). PlaceholderFormat(database.GetPlaceholderFormat()). RunWith(tx). ScanContext(ctx, &o.ID, &o.OwnerID, &o.OrgType, &o.Name, &o.Slug, &o.Image, &o.Timezone, - &o.Settings, &o.IsActive, &o.CreatedOn, &o.UpdatedOn, &o.OwnerName) + &o.Settings, &o.IsActive, &o.CreatedOn, &o.UpdatedOn, &o.Visibility, &o.OwnerName) if err != nil { if err == sql.ErrNoRows { return nil @@ -165,7 +174,8 @@ func (o *Organization) Store(ctx context.Context) error { Insert("organizations"). Columns("owner_id", "org_type", "name", "slug", "image", "timezone", "settings", "is_active"). - Values(o.OwnerID, o.OrgType, o.Name, o.Slug, o.Image, o.Timezone, settings, o.IsActive). + Values(o.OwnerID, o.OrgType, o.Name, o.Slug, o.Image, o.Timezone, + settings, o.IsActive). Suffix(`RETURNING id, created_on, updated_on`). PlaceholderFormat(database.GetPlaceholderFormat()). RunWith(tx). @@ -181,6 +191,7 @@ func (o *Organization) Store(ctx context.Context) error { Set("timezone", o.Timezone). Set("settings", settings). Set("is_active", o.IsActive). + Set("visibility", o.Visibility). Where("id = ?", o.ID). Suffix(`RETURNING (updated_on)`). PlaceholderFormat(database.GetPlaceholderFormat()). diff --git a/models/schema.sql b/models/schema.sql index bdbf4b5..c01f32f 100644 --- a/models/schema.sql +++ b/models/schema.sql @@ -73,6 +73,11 @@ CREATE TYPE totals_meta_type AS ENUM ( 'DEVICE' ); +CREATE TYPE public_visibility AS ENUM ( + 'PUBLIC', + 'HIDDEN' +) + CREATE TABLE users ( id SERIAL PRIMARY KEY, @@ -101,6 +106,7 @@ CREATE TABLE organizations ( image VARCHAR(1024) DEFAULT '', settings JSONB DEFAULT '{}', timezone VARCHAR(20) NOT NULL DEFAULT 'UTC', + visibility public_visibility DEFAULT 'PUBLIC', is_active BOOLEAN DEFAULT TRUE, created_on TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP @@ -153,6 +159,7 @@ CREATE TABLE base_urls ( counter INT DEFAULT 0, parse_attempts INT DEFAULT 0, last_parse_attempt TIMESTAMPTZ, + visibility public_visibility DEFAULT 'PUBLIC', created_on TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_on TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP ); diff --git a/templates/admin_org_detail.html b/templates/admin_org_detail.html index 3a8eb6e..6997b9f 100644 --- a/templates/admin_org_detail.html +++ b/templates/admin_org_detail.html @@ -31,6 +31,10 @@ {{.pd.Data.created_on}} {{formatDate .org.CreatedOn}} + + {{.pd.Data.visibility}} + {{.org.Visibility}} + {{.pd.Data.is_active}} diff --git a/templates/admin_update_org_type.html b/templates/admin_update_org_type.html index 1a3ec2d..f6bd525 100644 --- a/templates/admin_update_org_type.html +++ b/templates/admin_update_org_type.html @@ -19,13 +19,26 @@ {{ with .errors.OrgType }}

{{ . }}

{{ end }} +
+ + + {{ with .errors.Visibility }} +

{{ . }}

+ {{ end }} +
+