209 lines
5.3 KiB
Go
209 lines
5.3 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
"MobileMkch/models"
|
|
)
|
|
|
|
const (
|
|
BaseURL = "https://mkch.pooziqo.xyz"
|
|
ApiURL = BaseURL + "/api"
|
|
)
|
|
|
|
type Client struct {
|
|
httpClient *http.Client
|
|
baseURL string
|
|
debug bool
|
|
}
|
|
|
|
func NewClient() *Client {
|
|
return &Client{
|
|
httpClient: &http.Client{
|
|
Timeout: 30 * time.Second,
|
|
},
|
|
baseURL: ApiURL,
|
|
debug: false,
|
|
}
|
|
}
|
|
|
|
func (c *Client) EnableDebug(enable bool) {
|
|
c.debug = enable
|
|
}
|
|
|
|
func (c *Client) makeRequest(url string) ([]byte, error) {
|
|
if c.debug {
|
|
fmt.Printf("[API] Запрос: %s\n", url)
|
|
}
|
|
|
|
resp, err := c.httpClient.Get(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ошибка запроса: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ошибка чтения ответа: %w", err)
|
|
}
|
|
|
|
if c.debug {
|
|
fmt.Printf("[API] Статус: %d, Длина ответа: %d байт\n", resp.StatusCode, len(body))
|
|
if len(body) < 500 {
|
|
fmt.Printf("[API] Ответ: %s\n", string(body))
|
|
}
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, &models.APIError{
|
|
Message: fmt.Sprintf("HTTP %d: %s", resp.StatusCode, string(body)),
|
|
Code: resp.StatusCode,
|
|
}
|
|
}
|
|
|
|
return body, nil
|
|
}
|
|
|
|
func (c *Client) GetBoards() ([]models.Board, error) {
|
|
url := c.baseURL + "/boards/"
|
|
body, err := c.makeRequest(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ошибка получения досок: %w", err)
|
|
}
|
|
|
|
var boards []models.Board
|
|
if err := json.Unmarshal(body, &boards); err != nil {
|
|
if c.debug {
|
|
fmt.Printf("[API] Ошибка парсинга JSON: %v\n", err)
|
|
fmt.Printf("[API] Ответ был: %s\n", string(body))
|
|
}
|
|
return nil, fmt.Errorf("ошибка парсинга досок: %w", err)
|
|
}
|
|
|
|
if c.debug {
|
|
fmt.Printf("[API] Получено досок: %d\n", len(boards))
|
|
}
|
|
|
|
return boards, nil
|
|
}
|
|
|
|
func (c *Client) GetThreads(boardCode string) ([]models.Thread, error) {
|
|
url := fmt.Sprintf("%s/board/%s", c.baseURL, boardCode)
|
|
body, err := c.makeRequest(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ошибка получения тредов доски %s: %w", boardCode, err)
|
|
}
|
|
|
|
var threads []models.Thread
|
|
if err := json.Unmarshal(body, &threads); err != nil {
|
|
if c.debug {
|
|
fmt.Printf("[API] Ошибка парсинга JSON тредов: %v\n", err)
|
|
fmt.Printf("[API] Ответ был: %s\n", string(body))
|
|
}
|
|
return nil, fmt.Errorf("ошибка парсинга тредов: %w", err)
|
|
}
|
|
|
|
if c.debug {
|
|
fmt.Printf("[API] Получено тредов в /%s/: %d\n", boardCode, len(threads))
|
|
}
|
|
|
|
return threads, nil
|
|
}
|
|
|
|
func (c *Client) GetThread(boardCode string, threadID int) (*models.ThreadDetail, error) {
|
|
url := fmt.Sprintf("%s/board/%s/thread/%d", c.baseURL, boardCode, threadID)
|
|
body, err := c.makeRequest(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ошибка получения треда %d: %w", threadID, err)
|
|
}
|
|
|
|
var thread models.ThreadDetail
|
|
if err := json.Unmarshal(body, &thread); err != nil {
|
|
if c.debug {
|
|
fmt.Printf("[API] Ошибка парсинга JSON треда: %v\n", err)
|
|
fmt.Printf("[API] Ответ был: %s\n", string(body))
|
|
}
|
|
return nil, fmt.Errorf("ошибка парсинга треда: %w", err)
|
|
}
|
|
|
|
if c.debug {
|
|
fmt.Printf("[API] Получен тред: ID=%d, Title=%s\n", thread.ID, thread.Title)
|
|
}
|
|
|
|
return &thread, nil
|
|
}
|
|
|
|
func (c *Client) GetComments(boardCode string, threadID int) ([]models.Comment, error) {
|
|
url := fmt.Sprintf("%s/board/%s/thread/%d/comments", c.baseURL, boardCode, threadID)
|
|
body, err := c.makeRequest(url)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("ошибка получения комментариев треда %d: %w", threadID, err)
|
|
}
|
|
|
|
var comments []models.Comment
|
|
if err := json.Unmarshal(body, &comments); err != nil {
|
|
if c.debug {
|
|
fmt.Printf("[API] Ошибка парсинга JSON комментариев: %v\n", err)
|
|
fmt.Printf("[API] Ответ был: %s\n", string(body))
|
|
}
|
|
return nil, fmt.Errorf("ошибка парсинга комментариев: %w", err)
|
|
}
|
|
|
|
if c.debug {
|
|
fmt.Printf("[API] Получено комментариев: %d\n", len(comments))
|
|
}
|
|
|
|
return comments, nil
|
|
}
|
|
|
|
func (c *Client) GetFullThread(boardCode string, threadID int) (*models.ThreadDetail, []models.Comment, error) {
|
|
threadChan := make(chan *models.ThreadDetail, 1)
|
|
commentsChan := make(chan []models.Comment, 1)
|
|
errorChan := make(chan error, 2)
|
|
|
|
go func() {
|
|
thread, err := c.GetThread(boardCode, threadID)
|
|
if err != nil {
|
|
errorChan <- fmt.Errorf("ошибка получения треда: %w", err)
|
|
return
|
|
}
|
|
threadChan <- thread
|
|
}()
|
|
|
|
go func() {
|
|
comments, err := c.GetComments(boardCode, threadID)
|
|
if err != nil {
|
|
errorChan <- fmt.Errorf("ошибка получения комментариев: %w", err)
|
|
return
|
|
}
|
|
commentsChan <- comments
|
|
}()
|
|
|
|
var thread *models.ThreadDetail
|
|
var comments []models.Comment
|
|
var errors []error
|
|
|
|
for i := 0; i < 2; i++ {
|
|
select {
|
|
case t := <-threadChan:
|
|
thread = t
|
|
case c := <-commentsChan:
|
|
comments = c
|
|
case err := <-errorChan:
|
|
errors = append(errors, err)
|
|
case <-time.After(30 * time.Second):
|
|
return nil, nil, fmt.Errorf("тайм-аут получения треда")
|
|
}
|
|
}
|
|
|
|
if len(errors) > 0 {
|
|
return nil, nil, errors[0]
|
|
}
|
|
|
|
return thread, comments, nil
|
|
}
|