mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-26 20:31:11 +08:00
204 lines
4.2 KiB
Go
204 lines
4.2 KiB
Go
package yandex
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"net/http/cookiejar"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/AlexxIT/go2rtc/pkg/core"
|
|
)
|
|
|
|
type Session struct {
|
|
token string
|
|
client *http.Client
|
|
}
|
|
|
|
var sessions = map[string]*Session{}
|
|
var sessionsMu sync.Mutex
|
|
|
|
func GetSession(token string) (*Session, error) {
|
|
sessionsMu.Lock()
|
|
defer sessionsMu.Unlock()
|
|
|
|
if session, ok := sessions[token]; ok {
|
|
return session, nil
|
|
}
|
|
|
|
session := &Session{token: token}
|
|
if err := session.Login(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sessions[token] = session
|
|
|
|
return session, nil
|
|
}
|
|
|
|
func (s *Session) Login() error {
|
|
req, err := http.NewRequest(
|
|
"POST", "https://mobileproxy.passport.yandex.net/1/bundle/auth/x_token/",
|
|
strings.NewReader("type=x-token&retpath=https%3A%2F%2Fwww.yandex.ru"),
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
req.Header.Set("Ya-Consumer-Authorization", "OAuth "+s.token)
|
|
|
|
res, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var auth struct {
|
|
PassportHost string `json:"passport_host"`
|
|
Status string `json:"status"`
|
|
TrackId string `json:"track_id"`
|
|
}
|
|
if err = json.NewDecoder(res.Body).Decode(&auth); err != nil {
|
|
return err
|
|
}
|
|
|
|
if auth.Status != "ok" {
|
|
return errors.New("yandex: login error: " + auth.Status)
|
|
}
|
|
|
|
s.client = &http.Client{Timeout: 15 * time.Second}
|
|
s.client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
|
return http.ErrUseLastResponse
|
|
}
|
|
s.client.Jar, _ = cookiejar.New(nil)
|
|
|
|
res, err = s.client.Get(auth.PassportHost + "/auth/session/?track_id=" + auth.TrackId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
s.client.CheckRedirect = nil
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Session) Get(url string) (*http.Response, error) {
|
|
return s.client.Get(url)
|
|
}
|
|
|
|
func (s *Session) GetCSRF() (string, error) {
|
|
res, err := s.Get("https://yandex.ru/quasar")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
body, err := io.ReadAll(res.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
token := core.Between(string(body), `"csrfToken2":"`, `"`)
|
|
return token, nil
|
|
}
|
|
|
|
func (s *Session) GetCookieString(url string) string {
|
|
req, err := http.NewRequest("GET", url, nil)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
for _, cookie := range s.client.Jar.Cookies(req.URL) {
|
|
req.AddCookie(cookie)
|
|
}
|
|
return req.Header.Get("Cookie")
|
|
}
|
|
|
|
func (s *Session) GetDevices() ([]Device, error) {
|
|
res, err := s.Get("https://iot.quasar.yandex.ru/m/v3/user/devices")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var data struct {
|
|
Households []struct {
|
|
All []Device `json:"all"`
|
|
} `json:"households"`
|
|
}
|
|
|
|
if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var devices []Device
|
|
for _, household := range data.Households {
|
|
devices = append(devices, household.All...)
|
|
}
|
|
return devices, nil
|
|
}
|
|
|
|
func (s *Session) GetSnapshotURL(deviceID string) (string, error) {
|
|
devices, err := s.GetDevices()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
for _, device := range devices {
|
|
if device.Id == deviceID {
|
|
return device.Parameters.SnapshotUrl, nil
|
|
}
|
|
}
|
|
|
|
return "", errors.New("yandex: can't get snapshot url for device: " + deviceID)
|
|
}
|
|
|
|
func (s *Session) WebrtcCreateRoom(deviceID string) (*Room, error) {
|
|
csrf, err := s.GetCSRF()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req, err := http.NewRequest(
|
|
"POST", "https://iot.quasar.yandex.ru/m/v3/user/devices/"+deviceID+"/webrtc/create-room",
|
|
strings.NewReader(`{"protocol":"whip"}`),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header.Add("Content-Type", "application/json")
|
|
req.Header.Add("X-CSRF-Token", csrf)
|
|
|
|
res, err := s.client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var data struct {
|
|
Result Room `json:"result"`
|
|
}
|
|
if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &data.Result, nil
|
|
}
|
|
|
|
type Device struct {
|
|
Id string `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Parameters struct {
|
|
SnapshotUrl string `json:"snapshot_url,omitempty"`
|
|
} `json:"parameters"`
|
|
}
|
|
|
|
type Room struct {
|
|
ServiceUrl string `json:"service_url"`
|
|
ServiceName string `json:"service_name"`
|
|
RoomId string `json:"room_id"`
|
|
ParticipantId string `json:"participant_id"`
|
|
Credentials string `json:"jwt"`
|
|
}
|