Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

publish.gno

4.26 Kb · 99 lines
 1package radio
 2
 3import (
 4	"strings"
 5
 6	"gno.land/p/nym-alexiscolin000/gnoradio/text/v0"
 7	"gno.land/r/nym-alexiscolin000/gnoradio/catalog/v1"
 8)
 9
10// Tracks enter and change through this realm: the catalog accepts
11// PublishFor, ImportFor and EditFor from the radio writer only, so a track
12// is in the station rotations from the transaction that publishes it, paid
13// by its publisher. Nothing waits for Sync, and no robot pays for it.
14
15// PublishTrack publishes a track by the caller's own artist profile (the
16// arguments are catalog.PublishFor's) and puts it on the air in the same
17// transaction: the main station, its genre station and New this week.
18func PublishTrack(cur realm, title string, genre int, duration, license, cmo, credits, audio, audioSHA, cover, coverSHA, splits, rights string) int {
19	caller := userCaller(cur)
20	noPayment()
21	id := catalog.PublishFor(cross(cur), caller, title, genre, duration, license, cmo, credits, audio, audioSHA, cover, coverSHA, splits, rights)
22	onAir(cur, id, true)
23	return id
24}
25
26// ImportTrack adds a curated or Audius track to an unclaimed artist (the
27// arguments are catalog.ImportFor's) and puts it on the air, New this week
28// left out: an import is not a new release. The catalog admin only, from its
29// wallet or a realm that holds the role (a launch import).
30func ImportTrack(cur realm, artistID int, title string, genre int, duration, license, credits, audio, audioSHA, cover, coverSHA, sourceURL, attribution string) int {
31	noPayment()
32	id := catalog.ImportFor(cross(cur), cur.Previous().Address(), artistID, title, genre, duration, license, credits, audio, audioSHA, cover, coverSHA, sourceURL, attribution)
33	onAir(cur, id, false)
34	return id
35}
36
37// maxImportBatch bounds ImportTracks: each track costs a few M gas once the
38// realms are loaded, so a full batch stays far under the block's gas.
39const maxImportBatch = 25
40
41// ImportTracks imports up to maxImportBatch tracks in one transaction, so the
42// realms load once for the batch instead of once per track. batch holds one
43// track per line ("\n"), ImportTrack's 12 arguments separated by tabs ("\t";
44// neither can appear in a valid field). All or nothing: a bad track panics the
45// whole transaction (a malformed line is named before anything is written). It returns the id of the last track. Admin only, as
46// ImportTrack.
47func ImportTracks(cur realm, batch string) int {
48	noPayment()
49	lines := strings.Split(batch, "\n")
50	if batch == "" || len(lines) > maxImportBatch {
51		panic("radio: a batch holds 1 to " + text.Itoa(maxImportBatch) + " tracks")
52	}
53	rows := make([][]string, len(lines))
54	for i, line := range lines { // the whole batch is read before anything is written
55		f := strings.Split(line, "\t")
56		if len(f) != 12 || !text.Digits(f[0]) || !text.Digits(f[2]) {
57			panic("radio: batch line " + text.Itoa(i+1) + ": 12 tab-separated fields expected, artist and genre in digits")
58		}
59		rows[i] = f
60	}
61	by, id, t := cur.Previous().Address(), 0, rd()
62	for _, f := range rows {
63		id = catalog.ImportFor(cross(cur), by, text.MustAtoi(f[0]), f[1], text.MustAtoi(f[2]), f[3], f[4], f[5], f[6], f[7], f[8], f[9], f[10], f[11])
64		airNext(t, id, false)
65	}
66	save(cur, t)
67	return id
68}
69
70// EditTrack fixes a track's details (the arguments are catalog.EditFor's).
71// A new genre or duration is applied to the stations in the same
72// transaction, as Refresh does; other details need nothing on air.
73func EditTrack(cur realm, trackID int, title string, genre int, duration, credits, audio, audioSHA, cover, coverSHA string) {
74	caller := userCaller(cur)
75	noPayment()
76	_, oldGenre, oldDur, _ := catalog.TrackBrief(trackID)
77	catalog.EditFor(cross(cur), caller, trackID, title, genre, duration, credits, audio, audioSHA, cover, coverSHA)
78	if _, g, d, _ := catalog.TrackBrief(trackID); g != oldGenre || d != oldDur {
79		t := rd()
80		refresh(cur, t, trackID)
81		save(cur, t)
82	}
83}
84
85// onAir ingests the track the catalog just added, with Sync's own code: it
86// is the next one (Sync and every add keep the stations level with the
87// catalog), so this is one track's work whatever the catalog size.
88func onAir(cur realm, id int, isNew bool) {
89	t := rd()
90	airNext(t, id, isNew)
91	save(cur, t)
92}
93
94func airNext(t *tx, id int, isNew bool) {
95	if n := id - t.synced(); n != 1 {
96		panic("radio: the stations are behind the catalog, call Sync first")
97	}
98	ingest(t, now(), 1, isNew)
99}