<commit_before>//
// attachment.go -- nntp attachements
//

package srnd

import (
	"bytes"
	"crypto/sha512"
	"encoding/base32"
	"encoding/base64"
	"errors"
	"io"
	"log"
	"mime"
	"mime/multipart"
	"net/textproto"
	"os"
	"path/filepath"
	"strings"
)

type NNTPAttachment interface {
	io.WriterTo
	io.Writer

	// the name of the file
	Filename() string
	// the filepath to the saved file
	Filepath() string
	// the mime type of the attachment
	Mime() string
	// the file extension of the attachment
	Extension() string
	// get the sha512 hash of the attachment
	Hash() []byte
	// do we need to generate a thumbnail?
	NeedsThumbnail() bool
	// mime header
	Header() textproto.MIMEHeader
	// make into a model
	ToModel(prefix string) AttachmentModel
	// base64'd file data
	Filedata() string
	// as raw string
	AsString() string
	// reset contents
	Reset()
	// get bytes
	Bytes() []byte
	// save to directory, filename is decided by the attachment
	Save(dir string) error
	// get body as io.ReadCloser
	OpenBody() (io.ReadCloser, error)
}

type nntpAttachment struct {
	ext      string
	mime     string
	filename string
	filepath string
	hash     []byte
	header   textproto.MIMEHeader
	body     *bytes.Buffer
	rawpath  string
	store    ArticleStore
}

func (self *nntpAttachment) OpenBody() (io.ReadCloser, error) {
	return os.Open(self.store.AttachmentFilepath(self.filepath))
}

func (self *nntpAttachment) Reset() {
	self.body = nil
	self.header = nil
	self.hash = nil
	self.filepath = ""
	self.filename = ""
	self.mime = ""
	self.ext = ""
	self.store = nil
}

func (self *nntpAttachment) ToModel(prefix string) AttachmentModel {
	return &attachment{
		prefix: prefix,
		Path:   self.Filepath(),
		Name:   self.Filename(),
	}
}<commit_msg>try fixing<commit_after>//
// attachment.go -- nntp attachements
//

package srnd

import (
	"bytes"
	"crypto/sha512"
	"encoding/base32"
	"encoding/base64"
	"errors"
	"io"
	"log"
	"mime"
	"mime/multipart"
	"net/textproto"
	"os"
	"path/filepath"
	"strings"
)

type NNTPAttachment interface {
	io.WriterTo
	io.Writer

	// the name of the file
	Filename() string
	// the filepath to the saved file
	Filepath() string
	// the mime type of the attachment
	Mime() string
	// the file extension of the attachment
	Extension() string
	// get the sha512 hash of the attachment
	Hash() []byte
	// do we need to generate a thumbnail?
	NeedsThumbnail() bool
	// mime header
	Header() textproto.MIMEHeader
	// make into a model
	ToModel(prefix string) AttachmentModel
	// base64'd file data
	Filedata() string
	// as raw string
	AsString() string
	// reset contents
	Reset()
	// get bytes
	Bytes() []byte
	// save to directory, filename is decided by the attachment
	Save(dir string) error
	// get body as io.ReadCloser
	OpenBody() (io.ReadCloser, error)
}

type nntpAttachment struct {
	ext      string
	mime     string
	filename string
	filepath string
	hash     []byte
	header   textproto.MIMEHeader
	body     *bytes.Buffer
	rawpath  string
	store    ArticleStore
}

type byteBufferReadCloser struct {
	b *bytes.Buffer
}

func (b *byteBufferReadCloser) Close() error {
	b.b.Reset()
	return nil
}

func (b *byteBufferReadCloser) Read(d []byte) (int, error) {
	return b.b.Read(d)
}

func (self *nntpAttachment) OpenBody() (io.ReadCloser, error) {
	if self.store != nil {
		return os.Open(self.store.AttachmentFilepath(self.filepath))
	} else {
		return &byteBufferReadCloser{
			self.body,
		}, nil
	}
}

func (self *nntpAttachment) Reset() {
	self.body = nil
	self.header = nil
	self.hash = nil
	self.filepath = ""
	self.filename = ""
	self.mime = ""
	self.ext = ""
	self.store = nil
}

func (self *nntpAttachment) ToModel(prefix string) AttachmentModel {
	return &attachment{
		prefix: prefix,
		Path:   self.Filepath(),
		Name:   self.Filename(),
	}
}
{'fraction_non_alphanumeric': 0.1164021164021164, 'fraction_numerical': 0.006349206349206349, 'mean_word_length': 3.453474676089517, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4791967', 'n_tokens_mistral': 1374, 'n_tokens_neox': 1345, 'n_words': 391}