fc2

package
v1.6.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 3, 2024 License: MIT Imports: 31 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrLiveStreamNotOnline = errors.New("live stream is not online")
	ErrRateLimit           = errors.New("API rate limited")
)
View Source
var (
	ErrWebSocketServerDisconnection = errors.New("server disconnected")
	ErrWebSocketPaidProgram         = errors.New("paid program")
	ErrWebSocketLoginRequired       = errors.New("login required")
	ErrWebSocketMultipleConnection  = errors.New("multiple connection error")
	ErrWebSocketStreamEnded         = errors.New("stream ended")
	ErrWebSocketEmptyPlaylist       = errors.New("server did not return a valid playlist")
)
View Source
var ErrUnknownLatency = errors.New("unknown latency")
View Source
var ErrUnknownQuality = errors.New("unknown quality")

Functions

func FormatOutput added in v1.6.0

func FormatOutput(
	outFormat string,
	meta *GetMetaData,
	labels map[string]string,
	ext string,
) (string, error)

func Login added in v1.3.0

func Login(ctx context.Context, opts ...LoginOption) error

Login to FC2 and fill the CookieJar.

You need to probably need to

func LoginLoop added in v1.3.0

func LoginLoop(
	ctx context.Context,
	duration time.Duration,
	opts ...LoginOption,
)

func PrepareFile added in v1.6.0

func PrepareFile(
	outFormat string,
	meta *GetMetaData,
	labels map[string]string,
	ext string,
) (fName string, err error)

Types

type ChannelData

type ChannelData struct {
	ChannelID           string                `json:"channelid"`
	UserID              string                `json:"userid"`
	Adult               int                   `json:"adult"`
	Twoshot             int                   `json:"twoshot"`
	Title               string                `json:"title"`
	Info                string                `json:"info"`
	Image               string                `json:"image"`
	LoginOnly           int                   `json:"login_only"`
	GiftLimit           int                   `json:"gift_limit"`
	GiftList            []ChannelDataGiftList `json:"gift_list"`
	CommentLimit        string                `json:"comment_limit"`
	Tfollow             int                   `json:"tfollow"`
	Tname               string                `json:"tname"`
	Fee                 int                   `json:"fee"`
	Amount              int                   `json:"amount"`
	Interval            int                   `json:"interval"`
	Category            string                `json:"category"`
	CategoryName        string                `json:"category_name"`
	IsOfficial          int                   `json:"is_official"`
	IsPremiumPublisher  int                   `json:"is_premium_publisher"`
	IsLinkShare         int                   `json:"is_link_share"`
	Ticketid            int                   `json:"ticketid"`
	IsPremium           int                   `json:"is_premium"`
	TicketPrice         int                   `json:"ticket_price"`
	TicketOnly          int                   `json:"ticket_only"`
	IsApp               int                   `json:"is_app"`
	IsVideo             int                   `json:"is_video"`
	IsREST              int                   `json:"is_rest"`
	Count               int                   `json:"count"`
	IsPublish           int                   `json:"is_publish"`
	IsLimited           int                   `json:"is_limited"`
	Start               int                   `json:"start"`
	Version             string                `json:"version"`
	Fc2Channel          Fc2Channel            `json:"fc2_channel"`
	ControlTag          string                `json:"control_tag"`
	PublishMethod       string                `json:"publish_method"`
	VideoStereo3D       interface{}           `json:"video_stereo3d"`
	VideoMapping        interface{}           `json:"video_mapping"`
	VideoHorizontalView interface{}           `json:"video_horizontal_view"`
}

type ChannelDataGiftList

type ChannelDataGiftList struct {
	ID   int      `json:"id"`
	Type int      `json:"type"`
	URL  []string `json:"url"`
	Name string   `json:"name"`
}

type Comment

type Comment struct {
	UserName        string `json:"user_name"`
	Comment         string `json:"comment"`
	Timestamp       int    `json:"timestamp"`
	EncryptedUserID string `json:"encrypted_user_id"`
	OrzToken        string `json:"orz_token"`
	Hash            string `json:"hash"`
	Color           string `json:"color"`
	Size            string `json:"size"`
	Lang            string `json:"lang"`
	Anonymous       int    `json:"anonymous"`
	History         int    `json:"history"`
}

type CommentArguments

type CommentArguments struct {
	Comments []Comment `json:"comments"`
}

type ControlDisconnectionArguments

type ControlDisconnectionArguments struct {
	Code int `json:"code"`
}

type ControlToken

type ControlToken struct {
	ChannelID string `json:"channel_id,omitempty"`
	UserID    string `json:"user_id,omitempty"`
	// Fc2ID is either a string when logged in, or the integer 0.
	Fc2ID          any `json:"fc2_id,omitempty"`
	OrzToken       any `json:"orz_token,omitempty"`
	SessionToken   any `json:"session_token,omitempty"`
	Premium        any `json:"premium,omitempty"`
	Mode           any `json:"mode,omitempty"`
	Language       any `json:"language,omitempty"`
	ClientType     any `json:"client_type,omitempty"`
	ClientApp      any `json:"client_app,omitempty"`
	ClientVersion  any `json:"client_version,omitempty"`
	AppInstallKey  any `json:"app_install_key,omitempty"`
	ChannelVersion any `json:"channel_version,omitempty"`
	ControlTag     any `json:"control_tag,omitempty"`
	Ipv6           any `json:"ipv6,omitempty"`
	Commentable    any `json:"commentable,omitempty"`
	ServiceID      any `json:"service_id,omitempty"`
	IP             any `json:"ip,omitempty"`
	UserName       any `json:"user_name,omitempty"`
	AdultAccess    any `json:"adult_access,omitempty"`
	AgentID        any `json:"agent_id,omitempty"`
	CountryCode    any `json:"country_code,omitempty"`
	PayMode        any `json:"pay_mode,omitempty"`
	jwt.RegisteredClaims
}

type FC2

type FC2 struct {
	*http.Client
	// contains filtered or unexported fields
}

func New added in v0.4.0

func New(client *http.Client, params *Params, channelID string) *FC2

func (*FC2) FetchPlaylist

func (f *FC2) FetchPlaylist(
	ctx context.Context,
	ws *WebSocket,
	conn *websocket.Conn,
	msgChan chan *WSResponse,
) (*Playlist, error)

func (*FC2) HandleWS

func (f *FC2) HandleWS(
	ctx context.Context,
	wsURL string,
	fnameStream string,
	fnameChat string,
) error

func (*FC2) Watch added in v0.4.0

func (f *FC2) Watch(ctx context.Context) (*GetMetaData, error)

type Fc2Channel

type Fc2Channel struct {
	Result      int           `json:"result"`
	UserID      int           `json:"userid"`
	Fc2ID       int           `json:"fc2id"`
	Adult       int           `json:"adult"`
	Title       string        `json:"title"`
	Description string        `json:"description"`
	URL         string        `json:"url"`
	Images      []interface{} `json:"images"`
}

type GetControlServerResponse

type GetControlServerResponse struct {
	URL          string `json:"url"`
	Orz          string `json:"orz"`
	OrzRaw       string `json:"orz_raw"`
	ControlToken string `json:"control_token"`
	Status       int    `json:"status"`
}

type GetMetaData

type GetMetaData struct {
	ChannelData ChannelData `json:"channel_data"`
	ProfileData ProfileData `json:"profile_data"`
	UserData    UserData    `json:"user_data"`
}

type GetMetaOption added in v1.2.0

type GetMetaOption func(*GetMetaOptions)

func WithRefetch added in v1.2.0

func WithRefetch() GetMetaOption

type GetMetaOptions

type GetMetaOptions struct {
	// contains filtered or unexported fields
}

type GetMetaResponse

type GetMetaResponse struct {
	Status int         `json:"status"`
	Data   GetMetaData `json:"data"`
}

type HLSInformation

type HLSInformation struct {
	Status                 int        `json:"status"`
	Playlists              []Playlist `json:"playlists"`
	PlaylistsHighLatency   []Playlist `json:"playlists_high_latency"`
	PlaylistsMiddleLatency []Playlist `json:"playlists_middle_latency"`
}

type Latency

type Latency int
const (
	LatencyUnknown Latency = 0
	LatencyLow     Latency = 1
	LatencyHigh    Latency = 2
	LatencyMid     Latency = 3
)

func LatencyFromMode

func LatencyFromMode(mode int) Latency

func LatencyParseString

func LatencyParseString(value string) Latency

func (Latency) String

func (l Latency) String() string

func (*Latency) UnmarshalText

func (l *Latency) UnmarshalText(text []byte) error

type LiveStream

type LiveStream struct {
	*http.Client
	ChannelID string
	// contains filtered or unexported fields
}

func NewLiveStream

func NewLiveStream(client *http.Client, channelID string) *LiveStream

func (*LiveStream) GetMeta

func (ls *LiveStream) GetMeta(
	ctx context.Context,
	options ...GetMetaOption,
) (*GetMetaData, error)

func (*LiveStream) GetWebSocketURL

func (ls *LiveStream) GetWebSocketURL(ctx context.Context) (string, error)

func (*LiveStream) IsOnline

func (ls *LiveStream) IsOnline(ctx context.Context, options ...GetMetaOption) (bool, error)

func (*LiveStream) WaitForOnline

func (ls *LiveStream) WaitForOnline(ctx context.Context, interval time.Duration) error

type LoginOption added in v1.3.0

type LoginOption func(*LoginOptions)

func WithHTTPClient added in v1.3.0

func WithHTTPClient(client *http.Client) LoginOption

type LoginOptions added in v1.3.0

type LoginOptions struct {
	// contains filtered or unexported fields
}

type OptionalParams

type OptionalParams struct {
	Quality                *Quality          `yaml:"quality,omitempty"`
	Latency                *Latency          `yaml:"latency,omitempty"`
	PacketLossMax          *int              `yaml:"packetLossMax,omitempty"`
	OutFormat              *string           `yaml:"outFormat,omitempty"`
	WriteChat              *bool             `yaml:"writeChat,omitempty"`
	WriteInfoJSON          *bool             `yaml:"writeInfoJson,omitempty"`
	WriteThumbnail         *bool             `yaml:"writeThumbnail,omitempty"`
	WaitForLive            *bool             `yaml:"waitForLive,omitempty"`
	WaitForQualityMaxTries *int              `yaml:"waitForQualityMaxTries,omitempty"`
	WaitPollInterval       *time.Duration    `yaml:"waitPollInterval,omitempty"`
	CookiesFile            *string           `yaml:"cookiesFile,omitempty"`
	CookiesRefreshDuration *time.Duration    `yaml:"cookiesRefreshDuration,omitempty"`
	Remux                  *bool             `yaml:"remux,omitempty"`
	RemuxFormat            *string           `yaml:"remuxFormat,omitempty"`
	Concat                 *bool             `yaml:"concat,omitempty"`
	KeepIntermediates      *bool             `yaml:"keepIntermediates,omitempty"`
	ScanDirectory          *string           `yaml:"scanDirectory,omitempty"`
	EligibleForCleaningAge *time.Duration    `yaml:"eligibleForCleaningAge,omitempty"`
	DeleteCorrupted        *bool             `yaml:"deleteCorrupted,omitempty"`
	ExtractAudio           *bool             `yaml:"extractAudio,omitempty"`
	Labels                 map[string]string `yaml:"labels,omitempty"`
}

func (*OptionalParams) Override

func (override *OptionalParams) Override(params *Params)

type Params

type Params struct {
	Quality                Quality           `yaml:"quality,omitempty"`
	Latency                Latency           `yaml:"latency,omitempty"`
	PacketLossMax          int               `yaml:"packetLossMax,omitempty"`
	OutFormat              string            `yaml:"outFormat,omitempty"`
	WriteChat              bool              `yaml:"writeChat,omitempty"`
	WriteInfoJSON          bool              `yaml:"writeInfoJson,omitempty"`
	WriteThumbnail         bool              `yaml:"writeThumbnail,omitempty"`
	WaitForLive            bool              `yaml:"waitForLive,omitempty"`
	WaitForQualityMaxTries int               `yaml:"waitForQualityMaxTries,omitempty"`
	WaitPollInterval       time.Duration     `yaml:"waitPollInterval,omitempty"`
	CookiesFile            string            `yaml:"cookiesFile,omitempty"`
	CookiesRefreshDuration time.Duration     `yaml:"cookiesRefreshDuration,omitempty"`
	Remux                  bool              `yaml:"remux,omitempty"`
	RemuxFormat            string            `yaml:"remuxFormat,omitempty"`
	Concat                 bool              `yaml:"concat,omitempty"`
	KeepIntermediates      bool              `yaml:"keepIntermediates,omitempty"`
	ScanDirectory          string            `yaml:"scanDirectory,omitempty"`
	EligibleForCleaningAge time.Duration     `yaml:"eligibleForCleaningAge,omitempty"`
	DeleteCorrupted        bool              `yaml:"deleteCorrupted,omitempty"`
	ExtractAudio           bool              `yaml:"extractAudio,omitempty"`
	Labels                 map[string]string `yaml:"labels,omitempty"`
}
var DefaultParams Params = Params{
	Quality:                Quality1_2MBps,
	Latency:                LatencyMid,
	PacketLossMax:          20,
	OutFormat:              "{{ .Date }} {{ .Title }} ({{ .ChannelName }}).{{ .Ext }}",
	WriteChat:              false,
	WriteInfoJSON:          false,
	WriteThumbnail:         false,
	WaitForLive:            true,
	WaitForQualityMaxTries: 10,
	WaitPollInterval:       5 * time.Second,
	CookiesFile:            "",
	CookiesRefreshDuration: 24 * time.Hour,
	Remux:                  true,
	RemuxFormat:            "mp4",
	Concat:                 true,
	KeepIntermediates:      false,
	ScanDirectory:          "",
	EligibleForCleaningAge: 48 * time.Hour,
	DeleteCorrupted:        true,
	ExtractAudio:           false,
	Labels:                 nil,
}

func (*Params) Clone

func (p *Params) Clone() *Params

type Playlist

type Playlist struct {
	Mode   int    `json:"mode"`
	Status int    `json:"status"`
	URL    string `json:"url"`
}

func ExtractAndMergePlaylists

func ExtractAndMergePlaylists(hlsInfo *HLSInformation) []Playlist

func GetPlaylistOrBest

func GetPlaylistOrBest(sortedPlaylists []Playlist, expectMode int) (*Playlist, error)

func SortPlaylists

func SortPlaylists(playlists []Playlist) []Playlist

type ProfileData

type ProfileData struct {
	UserID string `json:"userid"`
	Fc2ID  string `json:"fc2id"`
	Name   string `json:"name"`
	Info   string `json:"info"`
	Icon   string `json:"icon"`
	Image  string `json:"image"`
	Sex    string `json:"sex"`
	Age    string `json:"age"`
}

type Quality

type Quality int
const (
	QualityUnknown Quality = 0
	Quality150KBps Quality = 10
	Quality400KBps Quality = 20
	Quality1_2MBps Quality = 30
	Quality2MBps   Quality = 40
	Quality3MBps   Quality = 50
	QualitySound   Quality = 90
)

func QualityFromMode

func QualityFromMode(mode int) Quality

func QualityParseString

func QualityParseString(value string) Quality

func (Quality) String

func (q Quality) String() string

func (*Quality) UnmarshalText

func (q *Quality) UnmarshalText(text []byte) error

type UserData

type UserData struct {
	IsLogin       int         `json:"is_login"`
	UserID        int         `json:"userid"`
	Fc2ID         int         `json:"fc2id"`
	Icon          string      `json:"icon"`
	Name          string      `json:"name"`
	Point         interface{} `json:"point"`
	AdultAccess   interface{} `json:"adult_access"`
	Recauth       interface{} `json:"recauth"`
	IsPremiumUser interface{} `json:"is_premium_user"`
	GiftList      interface{} `json:"gift_list"`
	Stamina       interface{} `json:"stamina"`
}

type WSResponse

type WSResponse struct {
	ID        int             `json:"id,omitempty"`
	Name      string          `json:"name"`
	Arguments json.RawMessage `json:"arguments"`
}

type WebSocket

type WebSocket struct {
	*http.Client
	// contains filtered or unexported fields
}

func NewWebSocket

func NewWebSocket(
	client *http.Client,
	url string,
	healthCheckInterval time.Duration,
) *WebSocket

func (*WebSocket) Dial

func (w *WebSocket) Dial(ctx context.Context) (*websocket.Conn, error)

func (*WebSocket) GetHLSInformation

func (w *WebSocket) GetHLSInformation(
	ctx context.Context,
	conn *websocket.Conn,
	msgChan <-chan *WSResponse,
) (*HLSInformation, error)

func (*WebSocket) HeartbeatLoop added in v0.3.0

func (w *WebSocket) HeartbeatLoop(
	ctx context.Context,
	conn *websocket.Conn,
	msgChan <-chan *WSResponse,
) error

HeartbeatLoop sends a heartbeat to keep the ws alive.

The only way to exit the heartbeat loop is to have the WS socket closed or to cancel the context.

func (*WebSocket) Listen

func (w *WebSocket) Listen(
	ctx context.Context,
	conn *websocket.Conn,
	msgChan chan<- *WSResponse,
	commentChan chan<- *Comment,
) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL