diff --git a/server/Caddyfile b/server/Caddyfile index 4b409175..0a1ff8a9 100644 --- a/server/Caddyfile +++ b/server/Caddyfile @@ -9,6 +9,15 @@ respond "{\"m.server\": \"matrix.handmade.network:443\"}" header Content-Type application/json } +# Uncomment this ONLY FOR BETA! +# It disables all search engine indexing! +# If you do this on the real site you will destroy all the site's SEO! +# ONLY UNCOMMENT THIS IN BETA! +# handle /robots.txt { +# respond "User-agent: * +# Disallow: / +# " +# } handle /public/* { file_server { root /home/hmn/hmn diff --git a/src/config/types.go b/src/config/types.go index eccd2d00..20b1292a 100644 --- a/src/config/types.go +++ b/src/config/types.go @@ -72,11 +72,10 @@ type DiscordConfig struct { OAuthClientID string OAuthClientSecret string - GuildID string - MemberRoleID string - ShowcaseChannelID string - LibraryChannelID string - JamShowcaseChannelID string + GuildID string + MemberRoleID string + ShowcaseChannelID string + LibraryChannelID string } type EpisodeGuide struct { diff --git a/src/discord/gateway.go b/src/discord/gateway.go index 75075e63..c7503e99 100644 --- a/src/discord/gateway.go +++ b/src/discord/gateway.go @@ -598,7 +598,6 @@ func (bot *botInstance) messageCreateOrUpdate(ctx context.Context, msg *Message) logging.ExtractLogger(ctx).Error().Err(err).Msg("failed to process showcase message") return nil } - return nil } if msg.ChannelID == config.Config.Discord.LibraryChannelID { @@ -607,7 +606,6 @@ func (bot *botInstance) messageCreateOrUpdate(ctx context.Context, msg *Message) logging.ExtractLogger(ctx).Error().Err(err).Msg("failed to process library message") return nil } - return nil } err := UpdateSnippetTagsIfAny(ctx, bot.dbConn, msg) diff --git a/src/discord/history.go b/src/discord/history.go index 343d752f..d708964e 100644 --- a/src/discord/history.go +++ b/src/discord/history.go @@ -193,6 +193,7 @@ func handleHistoryMessage(ctx context.Context, dbConn *pgxpool.Pool, msg *Messag } break } + defer tx.Rollback(ctx) newMsg, err := SaveMessageAndContents(ctx, tx, msg) if err != nil { diff --git a/src/discord/showcase.go b/src/discord/showcase.go index a145d8af..da0ea888 100644 --- a/src/discord/showcase.go +++ b/src/discord/showcase.go @@ -61,16 +61,14 @@ func (bot *botInstance) processShowcaseMsg(ctx context.Context, msg *Message) er // ...and maybe make a snippet too, if the user wants us to duser, err := FetchDiscordUser(ctx, tx, newMsg.UserID) if err == nil && duser.HMNUser.DiscordSaveShowcase { - err = CreateMessageSnippets(ctx, tx, newMsg.UserID, msg.ID) + err = CreateMessageSnippets(ctx, tx, msg.ID) if err != nil { return oops.New(err, "failed to create snippet in gateway") } - } else { - if err == db.NotFound { - // this is fine, just don't create a snippet - } else { - return err - } + } else if err == db.NotFound { + // this is fine, just don't create a snippet + } else if err != nil { + return err } err = tx.Commit(ctx) @@ -148,11 +146,9 @@ func SaveMessage( guildID := msg.GuildID if guildID == nil { - /* - This is weird, but it can happen when we fetch messages from - history instead of receiving it from the gateway. In this case - we just assume it's from the HMN server. - */ + // This is weird, but it can happen when we fetch messages from + // history instead of receiving it from the gateway. In this case + // we just assume it's from the HMN server. guildID = &config.Config.Discord.GuildID } @@ -593,7 +589,13 @@ func CreateMessageSnippets(ctx context.Context, dbConn db.ConnOrTx, msgIDs ...st `, msgID, ) - if err != nil { + if err == db.NotFound { + logging.ExtractLogger(ctx).Warn(). + Str("messageID", msgID). + Stack(). + Msg("No record was found for this Discord message at all. Is it actually a message ID?") + continue + } else if err != nil { return oops.New(err, "failed to check for existing snippet for message %s", msgID) } existing := iexisting.(*existingSnippetResult) @@ -689,6 +691,8 @@ If no Discord user is linked, or no snippet exists, or whatever, this will do nothing and return no error. */ func UpdateSnippetTagsIfAny(ctx context.Context, dbConn db.ConnOrTx, msg *Message) error { + logging.ExtractLogger(ctx).Debug().Str("msgID", msg.ID).Msg("updating snippets for message (if any)") + tx, err := dbConn.Begin(ctx) if err != nil { return oops.New(err, "failed to start transaction") @@ -720,11 +724,51 @@ func UpdateSnippetTagsIfAny(ctx context.Context, dbConn db.ConnOrTx, msg *Messag if err != nil { return oops.New(err, "failed to look up user projects") } - projectIDs := make([]int, len(projects)) - for i, p := range projects { - projectIDs[i] = p.Project.ID + userTagIDs := make([]int, 0, len(projects)) + for _, p := range projects { + if p.Project.TagID != nil { + userTagIDs = append(userTagIDs, *p.Project.TagID) + } } + // Try to associate tags in the message with project tags in HMN. + // Match only tags for projects in which the current user is a collaborator. + messageTags := getDiscordTags(s.Snippet.Description) + type tagsRow struct { + Tag models.Tag `db:"tags"` + } + itUserTags, err := db.Query(ctx, tx, tagsRow{}, + ` + SELECT $columns + FROM + tags + WHERE + id = ANY ($1) + `, + userTagIDs, + ) + if err != nil { + return oops.New(err, "failed to fetch tags for user projects") + } + iUserTags := itUserTags.ToSlice() + + var tagIDs []int + for _, itag := range iUserTags { + tag := itag.(*tagsRow).Tag + for _, messageTag := range messageTags { + if tag.Text == messageTag { + userTagIDs = append(userTagIDs, tag.ID) + } + } + } + + logging.ExtractLogger(ctx).Info(). + Interface("messageTags", messageTags). + Interface("tagIDs", tagIDs). + Int("snippetID", s.Snippet.ID). + Str("discordMsgID", msg.ID). + Msg("adding tags to snippet based on Discord message") + // Delete any existing project tags for this snippet. We don't want to // delete other tags in case in the future we have manual tagging on the // website or whatever, and this would clear those out. @@ -743,39 +787,6 @@ func UpdateSnippetTagsIfAny(ctx context.Context, dbConn db.ConnOrTx, msg *Messag return oops.New(err, "failed to delete existing snippet tags") } - // Try to associate tags in the message with project tags in HMN. - // Match only tags for projects in which the current user is a collaborator. - messageTags := getDiscordTags(s.Snippet.Description) - type tagsRow struct { - Tag models.Tag `db:"tags"` - } - itUserTags, err := db.Query(ctx, tx, tagsRow{}, - ` - SELECT $columns - FROM - tags - JOIN handmade_project AS project ON project.tag = tags.id - JOIN handmade_user_projects AS user_project ON user_project.project_id = project.id - WHERE - project.id = ANY ($1) - `, - projectIDs, - ) - if err != nil { - return oops.New(err, "failed to fetch tags for user projects") - } - iUserTags := itUserTags.ToSlice() - - var tagIDs []int - for _, itag := range iUserTags { - tag := itag.(*tagsRow).Tag - for _, messageTag := range messageTags { - if tag.Text == messageTag { - tagIDs = append(tagIDs, tag.ID) - } - } - } - for _, tagID := range tagIDs { _, err = tx.Exec(ctx, `