/
MkRoomsForStarCol.go
271 lines (231 loc) · 8.63 KB
/
MkRoomsForStarCol.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/*!
Copyright © 2022 chouette.21.00@gmail.com
Released under the MIT license
https://opensource.org/licenses/mit-license.php
*/
package exsrapi
import (
"errors"
"fmt"
"log"
"os"
"sort"
"time"
"net/http"
"github.com/Chouette2100/srapi"
)
/*
星集め、種集めの対象とするルームの一覧を作成する。
Ver.0.0.0
Ver.1.0.0 メソッド ExtrRoomLiveByCtg() の名前を ExtrByCtg() に変更したことに対応する。
Ver.1.1.0 ExtrByCtg() の引数がポインターになったことへ対応する。
Ver.1.2.0 sort.Sort()をsort.Slice()に変更する。
*/
// 除外リスト
type ExclList map[int]string // 除外ルームIDリスト
// 除外リストの読み込み
func (el ExclList) Read(
category string,
exclfilename string,
) (
err error,
) {
log.Printf("%-9s ******************* ExclList.Read() *******************\n", category)
fileEXCL, err := os.OpenFile(exclfilename, os.O_RDONLY, 0644)
if err != nil {
// 除外リストファイルをオープンできなかった場合
err = fmt.Errorf("os.OpenFile(): %w", err)
return err
}
defer fileEXCL.Close()
var roomid int
var roomname string
for {
nitem, _ := fmt.Fscanf(fileEXCL, "%d%s\n", &roomid, &roomname)
// log.Printf(" nitem =%d err=<%v> url=%s tstr=<%s>\n", nitem, err, url, tstr)
if nitem != 2 {
if nitem != 0 {
// 読み込みに失敗した場合
err = errors.New("fmt.Fscanf(): unexpected number of items. no=" + fmt.Sprintf("%d", nitem))
return err
}
// 読み込みが終わった場合
break
}
el[roomid] = roomname
log.Printf("%-9s excl. %-12d %s\n", category, roomid, roomname)
}
return nil
}
// 訪問済みルーム情報
type RoomVisit struct {
Rvlfn string
Category string
Roomvisit map[int]time.Time
}
// 配信ルーム訪問情報の読み込み
func (r *RoomVisit) Restore(
category string, // ジャンル名、ログのヘッダーに使う
rvlfn string, // 訪問ルームリストファイル名
aplmin int, // 訪問ルームリストの有効時間(分)
) (
err error,
) {
log.Printf("%-9s ******************* RoomVisit.Restore() *******************\n", category)
r.Rvlfn = rvlfn // 訪問済みルームリストファイル名、SaveRVL()での書き込み事故防止のために使う
r.Category = category // カテゴリー、SaveRVL()での書き込み事故防止のために使う
if len((*r).Roomvisit) != 0 {
// すでに訪問済みルームリストがある場合は、それを使う。
for roomid, rvtime := range (*r).Roomvisit {
if (*r).Roomvisit[roomid].Before(time.Now().Add(time.Duration(-aplmin) * time.Minute)) {
// 最後の訪問が一定時間以上前のルームは重複訪問対策用リストから削除する。
delete((*r).Roomvisit, roomid)
// log.Printf("M %20s deleted. (ltime=%s)\n", surl, rvtime.Format("01-02 15:04:05"))
log.Printf("%-9sM %-12d%s deleted.\n", category, roomid, rvtime.Format("01-02 15:04:05"))
}
}
} else {
// 訪問済みルームリストがない場合は初めての訪問候補リスト作成なのでファイルから読み込む。
fileRVL, err := os.OpenFile(rvlfn, os.O_RDONLY, 0644)
if err != nil {
// カテゴリーリストファイルをオープンできなかった場合
err = fmt.Errorf("os.OpenFile(): %w", err)
return err
}
defer fileRVL.Close()
var tstr string
var roomid int
for {
nitem, _ := fmt.Fscanf(fileRVL, "%q%d\n", &tstr, &roomid)
// log.Printf(" nitem =%d err=<%v> url=%s tstr=<%s>\n", nitem, err, url, tstr)
if nitem != 2 {
if nitem != 0 {
// 読み込みに失敗した場合
err = errors.New("fmt.Fscanf(): unexpected number of items. no=" + fmt.Sprintf("%d", nitem))
return err
}
// 読み込みが終わった場合
break
}
rvtime, err := time.Parse("2006/01/02 15:04:05 -0700 MST", tstr)
if err != nil {
// 日付の解析に失敗した場合
err = fmt.Errorf("time.Parse(): %w", err)
return err
}
log.Printf("%-9s\"%s\"\t%d\n", category, rvtime.Format("2006/01/02 15:04:05 -0700 MST"), roomid)
if rvtime.Before(time.Now().Add(time.Duration(-aplmin) * time.Minute)) {
// 一定時間経過した訪問情報は削除する
log.Printf("%-9sF %-12d%s deleted.\n", category, roomid, rvtime.Format("01-02 15:04:05"))
continue
}
(*r).Roomvisit[roomid] = rvtime
// log.Printf("F %12d used. (ltime=%s)\n", roomid, rvtime.Format("01-02 15:04:05"))
}
}
return nil
}
// 配信ルーム訪問情報の書き出し
func (r *RoomVisit) Save(
) (
err error,
) {
log.Printf("%-9s ******************* RoomVisit.Save() *******************\n", r.Category)
filervl, err := os.OpenFile(r.Rvlfn, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err != nil {
err = fmt.Errorf("os.OpenFile(): %w", err)
return err
}
// ルームリストをソートするためにいったんスライスにコピーする。
type srv struct {
vtm time.Time
roomid int
}
var srvl []srv
for roomid, tm := range r.Roomvisit {
srvl = append(srvl, srv{tm, roomid})
}
// 訪問時間でソートしておかないとひと目で状況が理解できない。
sort.Slice(srvl, func(i, j int) bool {
return srvl[i].vtm.Before(srvl[j].vtm)
})
// 訪問済みルームリストを書き出す。
for _, srv := range srvl {
fmt.Fprintf(filervl, "\"%s\"\t%d\n", srv.vtm.Format("2006/01/02 15:04:05 -0700 MST"), srv.roomid)
log.Printf("%-9s\"%s\"\t%d\n", r.Category, srv.vtm.Format("2006/01/02 15:04:05 -0700 MST"), srv.roomid)
}
filervl.Close()
return nil
}
// 星集め、種集めの対象とするルームの一覧を作成する。
func MkRoomsForStarCollec(
client *http.Client, // cookiejar付きHTTPクライアント
category string, // ジャンル名、ログのヘッダーにも使う
aplmin int, // 訪問後経過時間の最大値(分)
maxnoroom int, // 訪問候補として選択するルームの最大数
excllist *ExclList, // 除外するルームのリスト
roomvisit *map[int]time.Time, // 訪問済みルームリスト
) (
lives *[]srapi.Live, // 訪問候補ルームリスト
err error,
) {
log.Printf("%-9s ******************* MkRoomsForStarCollec() *******************\n", category)
// 現在配信中のすべてのルームのリストを取得する。
Roomonlives, err := srapi.ApiLiveOnlives(client)
if err != nil {
err = fmt.Errorf("srapi.ApiLiveOnlives(): %w", err)
return nil, err
}
// 指定したカテゴリーのルームのリストを取得する。
lives_c, err := Roomonlives.ExtrByCtg(category)
if err != nil {
err = fmt.Errorf("srapi.ExtrRoomLiveByCtg(): %w", err)
return nil, err
}
// 訪問候補ルームは配信を始めたばかりのルームから選ぶため開始時刻でソートする。
sort.Slice(*lives_c, func(i, j int) bool {
return (*lives_c)[i].Started_at > (*lives_c)[j].Started_at
})
lives = new([]srapi.Live)
i := 0
for _, live := range *lives_c {
// ジャンル内のすべてのルームについて繰り返す。
reason, exist := (*excllist)[live.Room_id]
starttime := time.Unix(live.Started_at, 0)
if exist {
// 除外リストに登録されているルームは除外する。
log.Printf("%-9sB %-12d%s in EL. %s\n", category, live.Room_id, starttime.Format("01-02 15:04:05"), reason)
continue
}
if starttime.Before(time.Now().Add(time.Duration(-aplmin) * time.Minute)) {
// 配信開始から一定時間経過したルームの訪問情報は削除されており視聴の可否が判断できないので無視する
log.Printf("%-9sO %-12d%s >%dmin. \n", category, live.Room_id, starttime.Format("01-02 15:04:05"), aplmin)
continue
}
ltime, exist := (*roomvisit)[live.Room_id]
if exist {
if starttime.Before(ltime) {
// 前回の視聴が終わってから今まで配信が続いている
// このケースでは星・種をもらえないのは確認済み
// delete(roomvisit, shortURL)
log.Printf("%-9sL %-12d%s Can't get a star twice in one delivery! (ltime=%s)\n", category,
live.Room_id, starttime.Format("01-02 15:04:06"), ltime.Format("15:04"))
continue
}
if time.Since(ltime) < time.Hour {
// 前回の視聴が終わってから新たに配信が行われているルーム
// ただし前回の視聴からまだ1時間経っていない <== ダメなの?
log.Printf("%-9sP %-12d Only %5.1fm have passed after last visit. (ltime=%s)\n", category,
live.Room_id, time.Since(ltime).Minutes(), ltime.Format("15:04:05"))
// continue ひとまずやってみる
}
}
// 取得したデータを戻り値(用の変数)に格納します。
*lives = append(*lives, live)
i++
if i >= maxnoroom {
break
}
}
return lives, nil
}