| SC Arguments: [Name:SC_ACTION Type:uint64 Value:'1' Name:SC_CODE Type:string Value:'// DeroBeats Registry Contract v5
// v3 + DERO AI fixes: length limits, duplicate FeatureSong, contentHash validation,
// Report rate-limit, TransferOwnership validation, GetSong bounds
//
// Return codes: 101=bad songSCID 102=bad title 103=bad artist 104=duplicate 105=anon
// 106=dup content_hash 107=already featured 108=length limit 109=invalid contentHash
// 110=already reported 111=newOwner empty
Function Initialize() Uint64
10 IF EXISTS("owner") THEN GOTO 999
20 DIM addr as String
25 LET addr = ADDRESS_STRING(SIGNER())
26 IF LEN(addr) < 1 THEN GOTO 999
30 STORE("owner", addr)
40 STORE("total_songs", 0)
45 STORE("featured_count", 0)
50 STORE("platform_name", "DeroBeats")
60 STORE("platform_url", "derobeats.tela")
98 RETURN 0
999 RETURN 1
End Function
// RegisterSong — 5 params, backward compatible
Function RegisterSong(songSCID String, title String, artist String, genre String, ipfsHash String) Uint64
10 DIM addr as String
15 LET addr = ADDRESS_STRING(SIGNER())
16 IF LEN(addr) < 1 THEN RETURN 105
20 IF LEN(songSCID) != 64 THEN RETURN 101
25 IF LEN(title) < 1 THEN RETURN 102
26 IF LEN(title) > 256 THEN RETURN 108
30 IF LEN(artist) < 1 THEN RETURN 103
31 IF LEN(artist) > 128 THEN RETURN 108
35 IF LEN(ipfsHash) > 128 THEN RETURN 108
40 IF LEN(genre) > 64 THEN RETURN 108
50 IF EXISTS(songSCID + "_registered") THEN RETURN 104
60 DIM count as Uint64
70 LET count = LOAD("total_songs")
80 STORE("song_" + count, songSCID)
90 STORE(songSCID + "_registered", 1)
100 STORE(songSCID + "_title", title)
110 STORE(songSCID + "_artist", artist)
120 STORE(songSCID + "_artist_addr", addr)
130 DIM g as String
135 IF LEN(genre) < 1 THEN LET g = "Unknown" ELSE LET g = genre
140 STORE(songSCID + "_genre", g)
150 STORE(songSCID + "_ipfs", ipfsHash)
160 STORE(songSCID + "_upvotes", 0)
170 STORE(songSCID + "_timestamp", BLOCK_TIMESTAMP())
180 STORE(songSCID + "_topoheight", BLOCK_TOPOHEIGHT())
190 DIM artist_count as Uint64
195 IF EXISTS(addr + "_song_count") THEN LET artist_count = LOAD(addr + "_song_count") ELSE LET artist_count = 0
200 STORE(addr + "_song_" + artist_count, songSCID)
210 STORE(addr + "_song_count", artist_count + 1)
220 DIM genre_count as Uint64
225 IF EXISTS(g + "_count") THEN LET genre_count = LOAD(g + "_count") ELSE LET genre_count = 0
230 STORE(g + "_song_" + genre_count, songSCID)
240 STORE(g + "_count", genre_count + 1)
250 STORE("total_songs", count + 1)
998 RETURN 0
End Function
// RegisterSongExt — 10 params
Function RegisterSongExt(songSCID String, title String, artist String, genre String, ipfsHash String, contentHash String, fileSizeStr String, mimeType String, durationStr String, previewArtCid String) Uint64
10 DIM addr as String
15 LET addr = ADDRESS_STRING(SIGNER())
16 IF LEN(addr) < 1 THEN RETURN 105
20 IF LEN(songSCID) != 64 THEN RETURN 101
25 IF LEN(title) < 1 THEN RETURN 102
26 IF LEN(title) > 256 THEN RETURN 108
30 IF LEN(artist) < 1 THEN RETURN 103
31 IF LEN(artist) > 128 THEN RETURN 108
35 IF LEN(ipfsHash) > 128 THEN RETURN 108
36 IF LEN(genre) > 64 THEN RETURN 108
37 IF LEN(mimeType) > 64 THEN RETURN 108
38 IF LEN(previewArtCid) > 128 THEN RETURN 108
50 IF EXISTS(songSCID + "_registered") THEN RETURN 104
51 IF LEN(contentHash) > 0 THEN GOTO 53 ELSE GOTO 60
53 IF LEN(contentHash) != 64 THEN RETURN 109
54 IF EXISTS("ch_" + contentHash) THEN RETURN 106
56 STORE("ch_" + contentHash, songSCID)
60 DIM count as Uint64
70 LET count = LOAD("total_songs")
80 STORE("song_" + count, songSCID)
90 STORE(songSCID + "_registered", 1)
100 STORE(songSCID + "_title", title)
110 STORE(songSCID + "_artist", artist)
120 STORE(songSCID + "_artist_addr", addr)
130 DIM g as String
135 IF LEN(genre) < 1 THEN LET g = "Unknown" ELSE LET g = genre
140 STORE(songSCID + "_genre", g)
150 STORE(songSCID + "_ipfs", ipfsHash)
160 STORE(songSCID + "_upvotes", 0)
170 STORE(songSCID + "_timestamp", BLOCK_TIMESTAMP())
180 STORE(songSCID + "_topoheight", BLOCK_TOPOHEIGHT())
185 IF LEN(contentHash) == 64 THEN STORE(songSCID + "_content_hash", contentHash)
186 IF LEN(fileSizeStr) > 0 THEN STORE(songSCID + "_file_size", fileSizeStr)
187 IF LEN(mimeType) > 0 THEN STORE(songSCID + "_mime_type", mimeType)
188 IF LEN(durationStr) > 0 THEN STORE(songSCID + "_duration", durationStr)
189 IF LEN(previewArtCid) > 0 THEN STORE(songSCID + "_preview_art_cid", previewArtCid)
190 DIM artist_count as Uint64
195 IF EXISTS(addr + "_song_count") THEN LET artist_count = LOAD(addr + "_song_count") ELSE LET artist_count = 0
200 STORE(addr + "_song_" + artist_count, songSCID)
210 STORE(addr + "_song_count", artist_count + 1)
220 DIM genre_count as Uint64
225 IF EXISTS(g + "_count") THEN LET genre_count = LOAD(g + "_count") ELSE LET genre_count = 0
230 STORE(g + "_song_" + genre_count, songSCID)
240 STORE(g + "_count", genre_count + 1)
250 STORE("total_songs", count + 1)
998 RETURN 0
End Function
// Update song metadata (artist only)
Function UpdateSong(songSCID String, title String, genre String, ipfsHash String) Uint64
10 IF LOAD(songSCID + "_artist_addr") != ADDRESS_STRING(SIGNER()) THEN GOTO 999
20 IF EXISTS(songSCID + "_registered") == 0 THEN GOTO 999
25 IF LEN(title) > 256 THEN GOTO 999
26 IF LEN(genre) > 64 THEN GOTO 999
27 IF LEN(ipfsHash) > 128 THEN GOTO 999
30 IF LEN(title) > 0 THEN STORE(songSCID + "_title", title)
40 IF LEN(genre) > 0 THEN STORE(songSCID + "_genre", genre)
50 IF LEN(ipfsHash) > 0 THEN STORE(songSCID + "_ipfs", ipfsHash)
60 STORE(songSCID + "_updated", BLOCK_TIMESTAMP())
98 RETURN 0
999 RETURN 1
End Function
// Feature song (owner only)
Function FeatureSong(songSCID String) Uint64
10 IF LOAD("owner") != ADDRESS_STRING(SIGNER()) THEN GOTO 999
20 IF EXISTS(songSCID + "_registered") == 0 THEN GOTO 999
25 IF EXISTS(songSCID + "_featured") == 1 THEN GOTO 27 ELSE GOTO 30
27 IF LOAD(songSCID + "_featured") == 1 THEN RETURN 107
30 DIM featured_count as Uint64
40 LET featured_count = LOAD("featured_count")
50 STORE("featured_" + featured_count, songSCID)
60 STORE("featured_count", featured_count + 1)
70 STORE(songSCID + "_featured", 1)
80 STORE(songSCID + "_featured_at", BLOCK_TIMESTAMP())
98 RETURN 0
999 RETURN 1
End Function
// Unfeature song (owner only)
Function UnfeatureSong(songSCID String) Uint64
10 IF LOAD("owner") != ADDRESS_STRING(SIGNER()) THEN GOTO 999
20 STORE(songSCID + "_featured", 0)
98 RETURN 0
999 RETURN 1
End Function
// Tag song (artist only)
Function TagSong(songSCID String, tag String) Uint64
10 IF EXISTS(songSCID + "_registered") == 0 THEN GOTO 999
15 IF LEN(tag) > 64 THEN RETURN 108
20 IF LOAD(songSCID + "_artist_addr") != ADDRESS_STRING(SIGNER()) THEN GOTO 999
30 DIM tag_count as Uint64
35 IF EXISTS(songSCID + "_tag_count") THEN LET tag_count = LOAD(songSCID + "_tag_count") ELSE LET tag_count = 0
40 STORE(songSCID + "_tag_" + tag_count, tag)
50 STORE(songSCID + "_tag_count", tag_count + 1)
60 DIM tagged_count as Uint64
65 IF EXISTS(tag + "_tagged_count") THEN LET tagged_count = LOAD(tag + "_tagged_count") ELSE LET tagged_count = 0
70 STORE(tag + "_tagged_" + tagged_count, songSCID)
80 STORE(tag + "_tagged_count", tagged_count + 1)
98 RETURN 0
999 RETURN 1
End Function
// Verify artist (owner only)
Function VerifyArtist(artistAddr String) Uint64
10 IF LOAD("owner") != ADDRESS_STRING(SIGNER()) THEN GOTO 999
20 STORE(artistAddr + "_verified", 1)
30 STORE(artistAddr + "_verified_at", BLOCK_TIMESTAMP())
98 RETURN 0
999 RETURN 1
End Function
// Report song (anyone, one per addr per song)
Function ReportSong(songSCID String, reason String) Uint64
10 DIM reporter as String
11 LET reporter = ADDRESS_STRING(SIGNER())
12 IF LEN(reporter) < 1 THEN GOTO 999
15 IF LEN(reason) > 256 THEN RETURN 108
17 IF EXISTS(reporter + "_reported_" + songSCID) THEN RETURN 110
20 IF EXISTS(songSCID + "_registered") == 0 THEN GOTO 999
25 DIM report_count as Uint64
26 IF EXISTS(songSCID + "_report_count") THEN LET report_count = LOAD(songSCID + "_report_count") ELSE LET report_count = 0
30 STORE(songSCID + "_report_" + report_count + "_by", reporter)
40 STORE(songSCID + "_report_" + report_count + "_reason", reason)
50 STORE(songSCID + "_report_" + report_count + "_time", BLOCK_TIMESTAMP())
60 STORE(songSCID + "_report_count", report_count + 1)
65 STORE(reporter + "_reported_" + songSCID, 1)
98 RETURN 0
999 RETURN 1
End Function
// Upvote song (one per address per song)
Function UpvoteSong(songSCID String) Uint64
10 DIM addr as String
15 LET addr = ADDRESS_STRING(SIGNER())
16 IF LEN(addr) < 1 THEN GOTO 999
20 IF EXISTS(songSCID + "_registered") == 0 THEN GOTO 999
30 IF EXISTS(addr + "_upvoted_" + songSCID) THEN GOTO 999
40 DIM upvotes as Uint64
50 LET upvotes = LOAD(songSCID + "_upvotes")
60 STORE(songSCID + "_upvotes", upvotes + 1)
70 STORE(addr + "_upvoted_" + songSCID, 1)
98 RETURN 0
999 RETURN 1
End Function
// Remove song (owner only)
Function RemoveSong(songSCID String) Uint64
10 IF LOAD("owner") != ADDRESS_STRING(SIGNER()) THEN GOTO 999
20 IF EXISTS(songSCID + "_registered") == 0 THEN GOTO 999
30 STORE(songSCID + "_removed", 1)
40 STORE(songSCID + "_removed_at", BLOCK_TIMESTAMP())
98 RETURN 0
999 RETURN 1
End Function
Function GetTotalSongs() Uint64
10 RETURN LOAD("total_songs")
End Function
Function GetSong(index Uint64) String
10 DIM total as Uint64
15 LET total = LOAD("total_songs")
20 IF index >= total THEN RETURN ""
25 RETURN LOAD("song_" + index)
End Function
Function GetArtistSongCount(artistAddr String) Uint64
10 RETURN LOAD(artistAddr + "_song_count")
End Function
Function GetGenreSongCount(genre String) Uint64
10 RETURN LOAD(genre + "_count")
End Function
Function GetFeaturedCount() Uint64
10 RETURN LOAD("featured_count")
End Function
// Transfer ownership (owner only)
Function TransferOwnership(newOwner String) Uint64
10 IF LOAD("owner") != ADDRESS_STRING(SIGNER()) THEN GOTO 999
15 IF LEN(newOwner) < 1 THEN RETURN 111
20 STORE("owner", newOwner)
98 RETURN 0
999 RETURN 1
End Function
'] |