Documentation
¶
Overview ¶
Package kooky contains routines to reach into cookie stores for various browsers and retrieve the cookies.
Example (ChromeSimpleMacOS) ¶
package main import ( "fmt" "os" "github.com/browserutils/kooky/browser/chrome" ) // on macOS: var cookieStorePath = "/Google/Chrome/Default/Cookies" func main() { // construct file path for the sqlite database containing the cookies dir, _ := os.UserConfigDir() // on macOS: "/<USER>/Library/Application Support/" cookieStoreFile := dir + cookieStorePath // read the cookies from the file // decryption is handled automatically for cookie := range chrome.TraverseCookies(cookieStoreFile).OnlyCookies() { fmt.Println(cookie) } }
Example (CookieJar) ¶
package main import ( "context" "fmt" "io" "log" "net/http" "net/url" "strings" "github.com/browserutils/kooky" _ "github.com/browserutils/kooky/browser/firefox" ) func main() { ctx := context.TODO() stores := kooky.FindAllCookieStores(ctx) var s kooky.CookieStore for _, store := range stores { if store.Browser() != `firefox` || !store.IsDefaultProfile() { continue } s = store break } // jar := s // only store cookies relevant for the target website in the cookie jar jar, _ := s.SubJar(ctx, kooky.FilterFunc(func(c *kooky.Cookie) bool { return kooky.Domain(`github.com`).Filter(c) || kooky.Domain(`.github.com`).Filter(c) })) u, _ := url.Parse(`https://github.com/settings/profile`) cookies := kooky.FilterCookies(ctx, jar.Cookies(u), kooky.Name(`logged_in`)).Collect(ctx) if len(cookies) == 0 { log.Fatal(`not logged in`) } client := http.Client{Jar: jar} resp, _ := client.Get(u.String()) body, _ := io.ReadAll(resp.Body) if !strings.Contains(string(body), `id="user_profile_name"`) { fmt.Print("not ") } fmt.Println("logged in") }
Output: logged in
Index ¶
- func ExportCookies[S CookieSeq | []*Cookie | []*http.Cookie](ctx context.Context, w io.Writer, cookies S)
- func FilterCookie[T Cookie | http.Cookie](ctx context.Context, cookie *T, filters ...Filter) bool
- func RegisterFinder(browser string, finder CookieStoreFinder)
- type BrowserInfo
- type Cookie
- type CookieSeq
- func (s CookieSeq) Chan(ctx context.Context) <-chan *Cookie
- func (s CookieSeq) Collect(ctx context.Context) Cookies
- func (s CookieSeq) Export(ctx context.Context, w io.Writer)
- func (s CookieSeq) Filter(ctx context.Context, filters ...Filter) CookieSeq
- func (s CookieSeq) FirstMatch(ctx context.Context, filters ...Filter) *Cookie
- func (s CookieSeq) Merge(seqs ...CookieSeq) CookieSeq
- func (s CookieSeq) OnlyCookies() CookieSeq
- func (s CookieSeq) ReadAllCookies(ctx context.Context) (Cookies, error)
- type CookieStore
- type CookieStoreFinder
- type CookieStoreSeq
- type Cookies
- type Filter
- func CreationAfter(u time.Time) Filter
- func CreationBefore(u time.Time) Filter
- func Domain(domain string) Filter
- func DomainContains(substr string) Filter
- func DomainHasPrefix(prefix string) Filter
- func DomainHasSuffix(suffix string) Filter
- func ExpiresAfter(u time.Time) Filter
- func ExpiresBefore(u time.Time) Filter
- func Name(name string) Filter
- func NameContains(substr string) Filter
- func NameHasPrefix(prefix string) Filter
- func NameHasSuffix(suffix string) Filter
- func Path(path string) Filter
- func PathContains(substr string) Filter
- func PathDepth(depth int) Filter
- func PathHasPrefix(prefix string) Filter
- func PathHasSuffix(suffix string) Filter
- func Value(value string) Filter
- func ValueContains(substr string) Filter
- func ValueHasPrefix(prefix string) Filter
- func ValueHasSuffix(suffix string) Filter
- func ValueLen(length int) Filter
- type FilterFunc
- type ValueFilterFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExportCookies ¶ added in v0.2.1
func ExportCookies[S CookieSeq | []*Cookie | []*http.Cookie](ctx context.Context, w io.Writer, cookies S)
ExportCookies() export "cookies" in the Netscape format.
curl, wget, ... use this format.
Example ¶
package main import ( "context" "net/http" "os" "github.com/browserutils/kooky" ) var cookieFile = `cookies.txt` func main() { var cookies = []*kooky.Cookie{{Cookie: http.Cookie{Domain: `.test.com`, Name: `test`, Value: `dGVzdA==`}}} file, err := os.OpenFile(cookieFile, os.O_RDWR|os.O_CREATE, 0644) if err != nil { // TODO: handle error return } defer file.Close() kooky.ExportCookies(context.TODO(), file, cookies) }
func FilterCookie ¶ added in v0.2.1
FilterCookie() tells if a "cookie" passes all "filters".
func RegisterFinder ¶ added in v0.2.1
func RegisterFinder(browser string, finder CookieStoreFinder)
RegisterFinder() registers CookieStoreFinder enabling automatic finding of cookie stores with FindAllCookieStores() and ReadCookies().
RegisterFinder() is called by init() in the browser subdirectories.
Types ¶
type BrowserInfo ¶ added in v0.2.3
type Cookie ¶
Cookie is an http.Cookie augmented with information obtained through the scraping process.
func (*Cookie) MarshalJSON ¶ added in v0.2.3
type CookieSeq ¶ added in v0.2.3
for-rangeable cookie retriever
func FilterCookies ¶ added in v0.2.1
func FilterCookies[S CookieSeq | ~[]*Cookie | ~[]*http.Cookie](ctx context.Context, cookies S, filters ...Filter) CookieSeq
Example ¶
package main import ( "context" "github.com/browserutils/kooky" _ "github.com/browserutils/kooky/browser/all" // register cookiestore finders ) var cookieName = `NID` func main() { ctx := context.TODO() cookies := kooky.AllCookies(). // automatic read Seq(). Filter( ctx, kooky.Valid, // remove expired cookies kooky.DomainContains(`google`), // cookie domain has to contain "google" kooky.Name(cookieName), // cookie name is "NID" kooky.Debug, // print cookies after applying previous filter ). Collect(ctx) // iterate and collect in a slice _ = cookies // do something }
func MergeCookieSeqs ¶ added in v0.2.3
func TraverseCookies ¶ added in v0.2.3
func (CookieSeq) Collect ¶ added in v0.2.3
Collect() is the same as ReadAllCookies but ignores the error
func (CookieSeq) FirstMatch ¶ added in v0.2.3
func (CookieSeq) OnlyCookies ¶ added in v0.2.3
sequence of non-nil cookies and nil errors
type CookieStore ¶ added in v0.2.1
type CookieStore interface { http.CookieJar BrowserInfo SubJar(context.Context, ...Filter) (http.CookieJar, error) TraverseCookies(...Filter) CookieSeq Close() error }
CookieStore represents a file, directory, etc containing cookies.
Call CookieStore.Close() after using any of its methods.
func FindAllCookieStores ¶ added in v0.2.1
func FindAllCookieStores(ctx context.Context) []CookieStore
FindAllCookieStores() tries to find cookie stores at default locations.
FindAllCookieStores() requires registered CookieStoreFinders.
Register cookie store finders for all browsers like this:
import _ "github.com/browserutils/kooky/browser/all"
Or only a specific browser:
import _ "github.com/browserutils/kooky/browser/chrome"
Example ¶
package main import ( "context" "fmt" "github.com/browserutils/kooky" _ "github.com/browserutils/kooky/browser/all" ) func main() { ctx := context.TODO() cookieStores := kooky.FindAllCookieStores(ctx) for _, store := range cookieStores { // CookieStore keeps files/databases open for repeated reads // close those when no longer needed defer store.Close() var filters = []kooky.Filter{ kooky.Valid, // remove expired cookies } for cookie := range store.TraverseCookies(filters...).OnlyCookies() { fmt.Printf( "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", store.Browser(), store.Profile(), store.FilePath(), cookie.Domain, cookie.Name, cookie.Value, cookie.Expires.Format(`2006.01.02 15:04:05`), ) } } }
type CookieStoreFinder ¶ added in v0.2.1
type CookieStoreFinder interface {
FindCookieStores() CookieStoreSeq
}
CookieStoreFinder tries to find cookie stores at default locations.
type CookieStoreSeq ¶ added in v0.2.3
type CookieStoreSeq iter.Seq2[CookieStore, error]
func TraverseCookieStores ¶ added in v0.2.3
func TraverseCookieStores(ctx context.Context) CookieStoreSeq
func (CookieStoreSeq) AllCookieStores ¶ added in v0.2.3
func (s CookieStoreSeq) AllCookieStores(ctx context.Context) []CookieStore
func (CookieStoreSeq) OnlyCookieStores ¶ added in v0.2.3
func (s CookieStoreSeq) OnlyCookieStores() CookieStoreSeq
sequence of non-nil cookie stores and nil errors
func (CookieStoreSeq) TraverseCookies ¶ added in v0.2.3
func (s CookieStoreSeq) TraverseCookies(ctx context.Context, filters ...Filter) CookieSeq
type Cookies ¶ added in v0.2.3
type Cookies []*Cookie
func AllCookies ¶ added in v0.2.3
func ReadCookies ¶ added in v0.2.1
Cookie retrieving functions in this package like TraverseCookies(), ReadCookies(), AllCookies() use registered cookiestore finders to read cookies. Erronous reads are skipped.
Register cookie store finders for all browsers like this:
import _ "github.com/browserutils/kooky/browser/all"
Or only a specific browser:
import _ "github.com/browserutils/kooky/browser/chrome"
Example (All) ¶
package main import ( "fmt" "github.com/browserutils/kooky" _ "github.com/browserutils/kooky/browser/all" // This registers all cookiestore finders! // _ "github.com/browserutils/kooky/browser/chrome" // load only the chrome cookiestore finder ) func main() { // try to find cookie stores in default locations and // read the cookies from them. // decryption is handled automatically. cookies := kooky.AllCookies() for _, cookie := range cookies { fmt.Println(cookie) } } var _ struct{} // ignore this - for correct working of the documentation tool
type Filter ¶ added in v0.2.1
Filter is used for filtering cookies in ReadCookies() functions. Filter order might be changed for performance reasons (omission of value decryption of filtered out cookies, etc).
A cookie passes the Filter if Filter.Filter returns true.
Example (Regex) ¶
package main import ( "context" "fmt" "net/http" "regexp" "github.com/browserutils/kooky" ) // example regex matching base64 strings var reBase64 = regexp.MustCompile(`^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$`) func main() { var cookies = []*kooky.Cookie{{Cookie: http.Cookie{Name: `test`, Value: `dGVzdA==`}}} ctx := context.Background() cookies = kooky.FilterCookies( ctx, cookies, ValueRegexMatch(reBase64), // filter cookies with the regex filter // kooky.Debug, // print cookies after applying the regex filter ).Collect(ctx) for _, cookie := range cookies { fmt.Println(cookie.Value) break // only first element } } func ValueRegexMatch(re *regexp.Regexp) kooky.Filter { return kooky.FilterFunc(func(cookie *kooky.Cookie) bool { return cookie != nil && re != nil && re.Match([]byte(cookie.Value)) }) }
Output: dGVzdA==
var Debug Filter = FilterFunc(func(cookie *Cookie) bool { fmt.Printf("%+#v\n", cookie) return true })
Debug prints the cookie.
Position Debug after the filter you want to test.
var HTTPOnly Filter = FilterFunc(func(cookie *Cookie) bool { return cookie != nil && cookie.HttpOnly })
var Secure Filter = FilterFunc(func(cookie *Cookie) bool { return cookie != nil && cookie.Secure })
func CreationAfter ¶ added in v0.2.1
func CreationBefore ¶ added in v0.2.1
func DomainContains ¶ added in v0.2.1
func DomainHasPrefix ¶ added in v0.2.1
func DomainHasSuffix ¶ added in v0.2.1
func ExpiresAfter ¶ added in v0.2.1
func ExpiresBefore ¶ added in v0.2.1
func NameContains ¶ added in v0.2.1
func NameHasPrefix ¶ added in v0.2.1
func NameHasSuffix ¶ added in v0.2.1
func PathContains ¶ added in v0.2.1
func PathHasPrefix ¶ added in v0.2.1
func PathHasSuffix ¶ added in v0.2.1
func ValueContains ¶ added in v0.2.1
func ValueHasPrefix ¶ added in v0.2.1
func ValueHasSuffix ¶ added in v0.2.1
type FilterFunc ¶ added in v0.2.1
func (FilterFunc) Filter ¶ added in v0.2.1
func (f FilterFunc) Filter(c *Cookie) bool
type ValueFilterFunc ¶ added in v0.2.2
func (ValueFilterFunc) Filter ¶ added in v0.2.2
func (f ValueFilterFunc) Filter(c *Cookie) bool