Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions router/consts/mime_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ const (
MimeImageJPEG = "image/jpeg"
MimeImageGIF = "image/gif"
MimeImageSVG = "image/svg+xml"
MimeImageWebP = "image/webp"
)
31 changes: 30 additions & 1 deletion router/utils/process_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

import (
"bytes"
"image/png"

Check failure on line 6 in router/utils/process_image.go

View workflow job for this annotation

GitHub Actions / Lint

File is not properly formatted (gofmt)
"io"

"github.com/sapphi-red/midec"
_ "github.com/sapphi-red/midec/webp"

Check failure on line 9 in router/utils/process_image.go

View workflow job for this annotation

GitHub Actions / Lint

blank-imports: a blank import should be only in a main or test package, or have a comment justifying it (revive)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank import になってるけどこれは理由がある?なければ削除してほしい

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

削除しました

@Takeno-hito Takeno-hito Apr 13, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import が sort されていなさそう(どちらかというと linter が落ちないのが悪い気がするが)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sortしました

"github.com/gofrs/uuid"
"github.com/labstack/echo/v4"

Expand Down Expand Up @@ -81,6 +82,34 @@
args.MimeType = consts.MimeImagePNG
args.Thumbnail = img // サムネイル画像より小さいという前提

case consts.MimeImageWebP:
Comment thread
uni-kakurenbo marked this conversation as resolved.
isAnimated, _ := midec.IsAnimated(src)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MUST: err ハンドリングをしてほしい

isAnimated, err := mide.IsAnimated(src)
if err != nil {
    return uuid.Nil, herror.InternalServerError(err)
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

エラーハンドリングを追加しました

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: isAnimated ですが、後続の 90 行目で判定をしているので、この isAnimated の宣言をもう少し後ろに置くと見やすいコードになると思います!

つまり、

seekErr チェック → isAnimated → err チェック → if isAnimated の順

if _, seekErr := src.Seek(0, io.SeekStart); seekErr != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seekErr => err

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reeにしました

return uuid.Nil, herror.InternalServerError(seekErr)
}
if isAnimated {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest

これ Seek より先に見ておけば余分な処理減って良さそう

return uuid.Nil, herror.BadRequest("animated WebP is not supported")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

want: アイコンもスタンプも animation 対応できるので、 TODO コメントを付けるかアニメーションも対応できるかどっちかはしてほしいかも!例えば

// TODO: アニメーションの WebP 対応 

とか

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

依存とかクロップとか考えて色々大変なので一旦TODOで書いておきました

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あとで issue 立ててもらえるとうれしい

}
img, err := p.Fit(src, maxImageSize, maxImageSize)
if err != nil {
switch err {
case imaging.ErrInvalidImageSrc:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors.Is を使ってほしいかも?
errors.Is(err, imaging.ErrInvalidImageSrc) という形

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors.Isを使うように変えました

return uuid.Nil, herror.BadRequest(badImage)
case imaging.ErrPixelLimitExceeded:
return uuid.Nil, herror.BadRequest(tooLargeImage)
default:
return uuid.Nil, herror.InternalServerError(err)
}
}
b := bytes.Buffer{}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits: (好みの問題です) 個人的には、 var b bytes.Buffer という形で宣言してある方がちょっと見やすいかも

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var bの書き方に変えました

if err := png.Encode(&b, img); err != nil {
return uuid.Nil, herror.InternalServerError(err)
}
args.Src = bytes.NewReader(b.Bytes())
args.FileSize = int64(b.Len())
args.MimeType = consts.MimeImagePNG
args.Thumbnail = img
Comment on lines +99 to +117

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

# Inspect all wrappers, helper calls, and imaging processor contracts.
rg -n --glob '*.go' \
  'SaveUploadIconImage|SaveUploadStampImage|saveUploadImage|type Processor interface|func .*Fit\(|\.Fit\(' \
  router service

Repository: traPtitech/traQ

Length of output: 2043


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- candidate files ---'
git ls-files | rg '(^|/)(process_image\.go|.*_test\.go|go\.mod)$' | head -200

printf '%s\n' '--- target file ---'
if [ -f router/utils/process_image.go ]; then
  cat -n router/utils/process_image.go
else
  printf '%s\n' 'router/utils/process_image.go not present'
fi

printf '%s\n' '--- related call sites and declarations ---'
rg -n --glob '*.go' \
  'SaveUploadIconImage|SaveUploadStampImage|saveUploadImage|type Processor interface|func .*Fit\(|\.Fit\(|midec\.IsAnimated|nativewebp\.Encode|\.Save\(' \
  . | head -400

printf '%s\n' '--- module declarations ---'
if [ -f go.mod ]; then
  rg -n 'imaging|midec|webp' go.mod go.sum
fi

Repository: traPtitech/traQ

Length of output: 2014


🌐 Web query:

traPtitech traQ router/utils/process_image.go SaveUploadIconImage saveUploadImage

💡 Result:

In the traQ backend repository (traPtitech/traQ), the file router/utils/process_image.go contains image processing logic, including the function saveUploadImage [1][2]. This function is used by higher-level handlers such as SaveUploadIconImage (for user icons) and others (e.g., for stamps) to process and store uploaded image files [1]. Recent developments in the repository indicate that saveUploadImage handles various image formats and includes validation and conversion logic [1]. For instance, a pull request (#2981) specifically modified this file to add support for WebP images, particularly for stamps [1]. The implementation details of saveUploadImage involve detecting the image MIME type, validating the content (such as rejecting unsupported animated formats), and potentially performing resizing or format conversion (e.g., converting to PNG) before saving the file [1]. When integrating new features like WebP support, developers must ensure that the logic within saveUploadImage correctly differentiates between file types—such as distinguishing between user icons and stamps—to prevent unintended side effects for image types that should remain restricted [1].

Citations:


🌐 Web query:

github.com/traPtitech/traQ imaging Processor Fit context Go

💡 Result:

In the traQ (traP Internal Messenger Application) project, "imaging" refers to the system's image processing functionality, which utilizes the third-party Go package github.com/disintegration/imaging [1][2]. The term "Fit" is a specific function provided by the imaging package [1]. Contextual details regarding their usage in traQ: 1. Imaging Processor: traQ uses the disintegration/imaging library for image handling, such as resizing, cropping, and converting uploaded images (e.g., icons or stamps) [3][2]. The application includes configuration options for this processing, such as maxPixels (to prevent excessive memory usage) and concurrency (to control CPU/memory usage for image tasks) [4]. 2. Fit Function: The imaging.Fit function is a specific method from the library used to resize images [1]. It scales an image down to fit within a specified bounding box (e.g., width x height) while maintaining the original aspect ratio [1]. In the context of traQ, this ensures that user-uploaded images are normalized to appropriate dimensions for the interface [3]. The imaging configuration in traQ is typically defined in config.yml, allowing administrators to tune performance based on their deployment needs [4].

Citations:


🌐 Web query:

github.com/sapphi-red/midec IsAnimated ErrFormat Go

💡 Result:

The Go library sapphi-red/midec is a multi-image detector used to determine if an image file (such as GIF, APNG, WebP, or HEIF/AVIF) is animated [1][2]. Regarding the specific terms in your query: IsAnimated: This is the primary function provided by the midec package [1][2]. It accepts an io.Reader and returns a boolean value indicating whether the input image is animated [1]. ErrFormat: This is not a component of the midec library itself, but rather a standard error variable defined in the Go standard library's image package (image.ErrFormat) [3][4]. It is commonly used in Go to indicate that an image format is unknown or not registered [3][5]. Because midec is designed to be similar to the standard image package, it may interact with or follow patterns similar to those where image.ErrFormat is used, but it is not part of the midec API [1][2]. In summary, midec provides the IsAnimated functionality to check for multi-image/animated content, while ErrFormat is a standard Go library constant for handling unknown image formats [1][3].

Citations:


🌐 Web query:

site:raw.githubusercontent.com/traPtitech/traQ process_image.go "func SaveUploadIconImage"

💡 Result:

No matching result was found for that exact query. The SaveUploadIconImage function may be on a non-default branch, in a moved file, or no longer present in the repository.


🌐 Web query:

site:github.com/traPtitech/traQ/blob/master/router/utils/process_image.go "saveUploadImage"

💡 Result:

saveUploadImage is defined in router/utils/process_image.go at line 32.

It:

  • Opens the multipart-uploaded file.
  • Enforces the configured file-size limit.
  • Accepts PNG, JPEG, and GIF.
  • Resizes images to the maximum dimensions.
  • Converts PNG/JPEG uploads to PNG.
  • Generates thumbnails for GIFs.
  • Saves the processed file through file.Manager.
  • Returns the saved file’s UUID. (raw.githubusercontent.com)

Citations:


🌐 Web query:

disintegration imaging Processor interface Fit Go context

💡 Result:

The terms in your query refer to two distinct and unrelated concepts in the Go programming ecosystem: 1. disintegration/imaging: This is a popular, lightweight Go package for image processing (e.g., resizing, cropping, rotation) [1][2][3]. It is not related to a Processor interface or Go context patterns. Its functions operate directly on types that satisfy the standard library's image.Image interface [1][4][5]. 2. Processor interface with context.Context: This is a common design pattern in Go for building extensible pipelines, workers, or middleware [6][7][8]. While not part of the standard library, it is frequently implemented using the following signature to ensure cancellation and timeout propagation [6][7][9]: type Processor interface { Process(ctx context.Context, r *Record) error } In this pattern, the context.Context is passed as the first argument to allow for graceful cancellation or deadline enforcement during the processing of a task [6][7][8]. Developers often use a functional adapter (e.g., ProcessorFunc) to allow simple functions to satisfy this interface, similar to the standard library's http.HandlerFunc [7]. If you were looking for a specific library that combines these, it is likely that you are using a custom wrapper or a different framework (such as Benthos or a background worker library) that utilizes the Processor interface pattern to handle image processing tasks or other data operations [7][8].

Citations:


🌐 Web query:

sapphi-red midec IsAnimated Go source Register WebP

💡 Result:

The sapphi-red/midec library is a pure Go multi-image (animated image) detector that supports formats such as GIF, APNG, WebP, and HEIF/AVIF [1][2]. To check if an image is animated, you use the IsAnimated function [1][2]. The usage pattern is as follows: import ( "fmt" "os" "github.com/sapphi-red/midec" _ "github.com/sapphi-red/midec/webp" // import to enable Animated WebP detection) func main { fp, _:= os.Open("image.webp") isAnimated:= midec.IsAnimated(fp) fmt.Println(isAnimated) } To add support for a new format or to register a specific handler, you use the midec.RegisterFormat function [1][2]. This function behaves similarly to the standard library's image.RegisterFormat and is typically called within an init function to register a format's header signature and its corresponding detection function [1][2]. Example: func init { midec.RegisterFormat("webp", webpHeader, isAnimated) } The library is designed with a pluggable architecture, allowing users to import specific sub-packages (e.g., _ "github.com/sapphi-red/midec/webp") to register and enable detection for that specific image format [1][2].

Citations:


🌐 Web query:

"func saveUploadImage" "imaging.Processor" traQ

💡 Result:

In the context of the traQ (traP Internal Messenger Application) backend, saveUploadImage is an internal function responsible for processing and saving uploaded images [1]. The function is typically located within the application's router utilities (e.g., router/utils/process_image.go) [1]. It manages the image upload pipeline, which includes: 1. Identification and validation of MIME types [1]. 2. Processing based on the file type (e.g., handling specific formats like WebP or standard images for stamps and icons) [1]. 3. Interaction with external image processing libraries—specifically github.com/disintegration/imaging—which is used within the traQ backend to handle image transformations [1][2]. The imaging.Processor refers to the functionality provided by the disintegration/imaging Go library, which is utilized by traQ for resizing, encoding, and other image manipulations during the upload process [1][2]. As an internal backend utility, saveUploadImage is not part of the public traQ API client library [3]. Developers looking to interact with traQ's image features should use the official API endpoints rather than attempting to call internal helper functions directly [3].

Citations:


🌐 Web query:

"SaveUploadStampImage" "context.Context" traQ

💡 Result:

In the traQ backend codebase, SaveUploadStampImage is a function responsible for handling the image processing and saving logic when a new stamp is uploaded [1]. It is not a public API endpoint, but rather an internal utility function within the server-side implementation [1]. It is often invoked in contexts where an image file needs to be processed and stored as a stamp [1]. The function receives a context.Context as an argument, which is standard practice in the traQ Go backend to handle request-scoped values, cancellations, and deadlines across asynchronous operations or service calls [2][3]. The function is closely related to other image-handling routines and has been updated in the past to support different image formats, such as WebP, specifically for stamps [1]. Because it is an internal backend function, developers interacting with the traQ system typically use the high-level API methods provided by the official SDKs (such as ChangeStampImage or CreateStamp) rather than calling SaveUploadStampImage directly [2][3]. These high-level API methods also accept a context.Context to maintain proper request management [2].

Citations:


🌐 Web query:

"midec.IsAnimated" "nativewebp.Encode" traQ

💡 Result:

The terms mentioned relate to Go-based image processing components often used in the context of the traQ messenger application or similar projects associated with Digital Creators Club traP. midec refers to a library (often seen as sapphi-red/midec or its WebAssembly port node-midec) that functions as a multi-image detector capable of identifying formats like Animated GIF, APNG, Animated WebP, and Animated HEIF/AVIF [1]. nativewebp is a pure Go implementation of a WebP encoder that does not require external C libraries like libwebp [2][3]. Within the nativewebp package, nativewebp.Encode is the primary function used to encode a single image into WebP format [2][4]. The package also supports animations through functions like EncodeAll, which handles multi-frame WebP files [2][3][5]. traQ is the open-source internal messenger application developed by the Digital Creators Club traP, written primarily in Go [6][7]. Components like image processing libraries are frequently integrated into such systems to handle media uploads and previews [6]. While these components may be used together in a software stack, there is no single standardized function named midec.IsAnimated that directly calls nativewebp.Encode in a public, monolithic API. Rather, midec is typically used to detect image characteristics, and nativewebp is used to encode/transcode them [2][1]. Developers often integrate these tools to perform tasks such as detecting animated media and subsequently re-encoding them into an optimized format like WebP [2][1][5].

Citations:


🌐 Web query:

site:github.com/traPtitech/traQ/pull/2981 process_image.go context

💡 Result:

The filename process_image.go is not a standard library component in the Go programming language, nor is it part of a universally defined framework. Instead, it is a common naming convention used by developers in specific Go-based projects to encapsulate image manipulation logic [1]. In software projects using this filename, process_image.go typically resides within utility or service directories (e.g., /router/utils/ or /internal/utils/) and is responsible for handling tasks such as: 1. Image Format Validation: Checking MIME types or file extensions to ensure the image meets project requirements [1]. 2. Processing Pipelines: Implementing logic for resizing, converting between formats (e.g., WebP to PNG), or compressing images [1]. 3. Metadata Management: Validating image properties or updating metadata during the upload or storage lifecycle [1]. 4. Error Handling: Mapping specific image processing failures (e.g., unsupported format or invalid animation) to appropriate system or HTTP responses [1]. If you have encountered this file in a specific codebase, it is a custom implementation tailored to that application's requirements for managing image assets.

Citations:


Propagate the request context through image processing.

Update SaveUploadIconImage, SaveUploadStampImage, and saveUploadImage to accept context.Context first. Pass it to m.Save, and check ctx.Err() before and after context-unaware calls such as midec.IsAnimated, p.Fit, and nativewebp.Encode.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@router/utils/process_image.go` around lines 99 - 117, Update
SaveUploadIconImage, SaveUploadStampImage, and saveUploadImage to accept
context.Context as their first parameter and propagate it through the call chain
to m.Save. Before and after each context-unaware call, including
midec.IsAnimated, p.Fit, and nativewebp.Encode, check ctx.Err() and return the
cancellation error when the context is done.

Source: Path instructions


case consts.MimeImageGIF:
// リサイズ
b, err := p.FitAnimationGIF(src, maxImageSize, maxImageSize)
Expand Down
Loading