Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ddex_app field for ddex tracks/playlists to discovery #7734

Merged
merged 4 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/common/src/models/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export type CollectionMetadata = {
offline?: OfflineCollectionMetadata
local?: boolean
release_date?: string
ddex_app?: string | null
}

export type CollectionDownloadReason = { is_from_favorites: boolean }
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/models/Track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ export type TrackMetadata = {
orig_filename: Nullable<string>
is_downloadable: boolean
is_original_available: boolean
ddex_app?: Nullable<string>

// Optional Fields
is_playlist_upload?: boolean
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/services/audius-api-client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export type APITrack = {
orig_filename: Nullable<string>
is_downloadable: boolean
is_original_available: boolean
ddex_app: Nullable<string>
}

export type APISearchTrack = Omit<
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
begin;

alter table tracks add column if not exists ddex_app varchar;
alter table playlists add column if not exists ddex_app varchar;

commit;
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def test_valid_parse_metadata(app):
"preview_start_seconds": None,
"audio_upload_id": None,
"placement_hosts": None,
"ddex_app": None,
},
"QmUpdatePlaylist1": {
"playlist_id": 1,
Expand All @@ -198,6 +199,7 @@ def test_valid_parse_metadata(app):
"is_album": False,
"is_private": False,
"is_image_autogenerated": None,
"ddex_app": None,
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ export interface PlaylistRow {
txhash?: string
upc?: string | null
updated_at: Date
ddex_app?: string | null
}
export interface PlayRow {
city?: string | null
Expand Down Expand Up @@ -639,6 +640,7 @@ export interface TrackRow {
track_segments: any
txhash?: string
updated_at: Date
ddex_app?: string | null
}
export interface TrendingParamRow {
genre?: string | null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ export type Playlists = {
slot: number | null;
metadata_multihash: string | null;
is_image_autogenerated: boolean;
ddex_app: string | null;
};

export type Plays = {
Expand Down Expand Up @@ -988,6 +989,7 @@ export type Tracks = {
is_original_available: boolean;
orig_file_cid: string | null;
orig_filename: string | null;
ddex_app: string | null;
};

export type TrendingResults = {
Expand Down
1 change: 1 addition & 0 deletions packages/discovery-provider/src/api/v1/models/playlists.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"favorite_count": fields.Integer(required=True),
"total_play_count": fields.Integer(required=True),
"user": fields.Nested(user_model, required=True),
"ddex_app": fields.String(allow_null=True),
},
)

Expand Down
1 change: 1 addition & 0 deletions packages/discovery-provider/src/api/v1/models/tracks.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
"play_count": fields.Integer(required=True),
"permalink": fields.String,
"is_streamable": fields.Boolean,
"ddex_app": fields.String(allow_null=True),
},
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Playlist(Base, RepresentableMixin):
upc = Column(String)
updated_at = Column(DateTime, nullable=False)
playlist_image_sizes_multihash = Column(String)
ddex_app = Column(String)
is_image_autogenerated = Column(
Boolean, nullable=False, server_default=text("false")
)
Expand Down
1 change: 1 addition & 0 deletions packages/discovery-provider/src/models/tracks/track.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class Track(Base, RepresentableMixin):
download = Column(JSONB())
is_scheduled_release = Column(Boolean, nullable=False, server_default=text("false"))
is_unlisted = Column(Boolean, nullable=False, server_default=text("false"))
ddex_app = Column(String)
field_visibility = Column(JSONB(True))
route_id = Column(String)
stem_of = Column(JSONB(True))
Expand Down
4 changes: 4 additions & 0 deletions packages/discovery-provider/src/schemas/playlist_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"is_image_autogenerated": {
"type": "boolean",
"default": false
},
"ddex_app": {
"type": ["string", "null"],
"default": null
}
},
"required": [],
Expand Down
9 changes: 8 additions & 1 deletion packages/discovery-provider/src/schemas/track_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@
],
"default": null
},
"ddex_app": {
"type": [
"string",
"null"
],
"default": null
},
"track_segments": {
"type": "array",
"minItems": 0,
Expand Down Expand Up @@ -602,4 +609,4 @@
]
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
EntityType,
ManageEntityParameters,
copy_record,
is_ddex_signer,
validate_signer,
)
from src.tasks.metadata import immutable_playlist_fields
Expand Down Expand Up @@ -344,6 +345,11 @@ def create_playlist(params: ManageEntityParameters):
tracks = params.metadata["playlist_contents"].get("track_ids", [])
tracks_with_index_time = []
last_added_to = None

ddex_app = None
if is_ddex_signer(params.signer):
ddex_app = params.signer

for track in tracks:
if "track" not in track or "time" not in track:
raise IndexingValidationError(
Expand Down Expand Up @@ -382,6 +388,7 @@ def create_playlist(params: ManageEntityParameters):
last_added_to=last_added_to,
is_current=False,
is_delete=False,
ddex_app=ddex_app,
)

update_playlist_routes_table(params, playlist_record, True)
Expand All @@ -405,6 +412,16 @@ def dispatch_challenge_playlist_upload(
)


def validate_update_ddex_playlist(params: ManageEntityParameters, playlist_record):
if playlist_record.ddex_app:
if playlist_record.ddex_app != params.signer or not is_ddex_signer(
params.signer
):
raise IndexingValidationError(
f"Signer {params.signer} does not have permission to {params.action} DDEX playlist {playlist_record.playlist_id}"
)


def update_playlist(params: ManageEntityParameters):
validate_playlist_tx(params)
# TODO ignore updates on deleted playlists?
Expand All @@ -416,6 +433,8 @@ def update_playlist(params: ManageEntityParameters):
): # override with last updated playlist is in this block
existing_playlist = params.new_records["Playlist"][playlist_id][-1]

validate_update_ddex_playlist(params, existing_playlist)

playlist_record = copy_record(
existing_playlist,
params.block_number,
Expand Down Expand Up @@ -445,6 +464,8 @@ def delete_playlist(params: ManageEntityParameters):
# override with last updated playlist is in this block
existing_playlist = params.new_records["Playlist"][params.entity_id][-1]

validate_update_ddex_playlist(params, existing_playlist)

deleted_playlist = copy_record(
existing_playlist,
params.block_number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
EntityType,
ManageEntityParameters,
copy_record,
is_ddex_signer,
validate_signer,
)
from src.tasks.metadata import immutable_track_fields
Expand Down Expand Up @@ -463,6 +464,9 @@ def create_track(params: ManageEntityParameters):
is_delete=False,
)

if is_ddex_signer(params.signer):
track_record.ddex_app = params.signer

update_track_routes_table(
params, track_record, params.metadata, params.pending_track_routes
)
Expand All @@ -484,6 +488,14 @@ def create_track(params: ManageEntityParameters):
params.add_record(track_id, track_record)


def validate_update_ddex_track(params: ManageEntityParameters, track_record):
if track_record.ddex_app:
if track_record.ddex_app != params.signer or not is_ddex_signer(params.signer):
raise IndexingValidationError(
f"Signer {params.signer} does not have permission to {params.action} DDEX track {track_record.track_id}"
)


def update_track(params: ManageEntityParameters):
handle = get_handle(params)
validate_track_tx(params)
Expand All @@ -495,6 +507,8 @@ def update_track(params: ManageEntityParameters):
): # override with last updated track is in this block
existing_track = params.new_records["Track"][track_id][-1]

validate_update_ddex_track(params, existing_track)

track_record = copy_record(
existing_track,
params.block_number,
Expand Down Expand Up @@ -528,6 +542,8 @@ def delete_track(params: ManageEntityParameters):
# override with last updated playlist is in this block
existing_track = params.new_records["Track"][params.entity_id][-1]

validate_update_ddex_track(params, existing_track)

deleted_track = copy_record(
existing_track,
params.block_number,
Expand Down
9 changes: 9 additions & 0 deletions packages/discovery-provider/src/tasks/entity_manager/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import os
from datetime import datetime
from enum import Enum
from typing import Dict, List, Literal, Set, Tuple, TypedDict, Union
Expand Down Expand Up @@ -479,3 +480,11 @@ def get_address_from_signature(signature):
message_hash, signature=signature["signature"]
)
return app_address.lower()


def is_ddex_signer(signer):
# TODO read from a table in the db after implementing UI to register a DDEX node
ddex_apps = os.getenv("audius_ddex_apps")
if ddex_apps:
return signer.removeprefix("0x") in ddex_apps.split(",")
return False
4 changes: 4 additions & 0 deletions packages/discovery-provider/src/tasks/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class TrackMetadata(TypedDict):
is_playlist_upload: Optional[bool]
ai_attribution_user_id: Optional[int]
placement_hosts: Optional[str]
ddex_app: Optional[str]


track_metadata_format: TrackMetadata = {
Expand Down Expand Up @@ -122,6 +123,7 @@ class TrackMetadata(TypedDict):
"is_playlist_upload": False,
"ai_attribution_user_id": None,
"placement_hosts": None,
"ddex_app": None,
}

# Required format for user metadata retrieved from the content system
Expand Down Expand Up @@ -157,6 +159,7 @@ class PlaylistMetadata(TypedDict):
is_image_autogenerated: Optional[bool]
is_stream_gated: Optional[bool]
stream_conditions: Optional[Any]
ddex_app: Optional[str]


playlist_metadata_format: PlaylistMetadata = {
Expand All @@ -170,6 +173,7 @@ class PlaylistMetadata(TypedDict):
"is_image_autogenerated": None,
"is_stream_gated": False,
"stream_conditions": None,
"ddex_app": None,
}

# Updates cannot directly modify these fields via metadata
Expand Down
2 changes: 2 additions & 0 deletions packages/es-indexer/src/types/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ export interface PlaylistRow {
'txhash': string;
'upc': string | null;
'updated_at': Date;
'ddex_app': string | null;
}
export interface PlayRow {
'city': string | null;
Expand Down Expand Up @@ -702,6 +703,7 @@ export interface TrackRow {
'track_segments': any;
'txhash': string;
'updated_at': Date;
'ddex_app': string | null;
}
export interface TrendingParamRow {
'genre': string | null;
Expand Down
4 changes: 3 additions & 1 deletion packages/libs/src/api/entityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type PlaylistParam = {
is_private: boolean
is_album: boolean
is_image_autogenerated: boolean
ddex_app?: string | null
}

/*
Expand Down Expand Up @@ -225,7 +226,8 @@ export class EntityManager extends Base {
description: playlist.description,
is_album: playlist.is_album,
is_private: playlist.is_private,
is_image_autogenerated: playlist.is_image_autogenerated
is_image_autogenerated: playlist.is_image_autogenerated,
ddex_app: playlist.ddex_app
}
this.creatorNode.validatePlaylistSchema(metadata)

Expand Down
1 change: 1 addition & 0 deletions packages/libs/src/services/creatorNode/CreatorNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export type PlaylistMetadata = {
is_album: boolean
is_private: boolean
is_image_autogenerated: boolean
ddex_app?: string | null
}

export type ProgressCB = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
"is_image_autogenerated": {
"type": "boolean",
"default": false
},
"ddex_app": {
"type": ["string", "null"],
"default": null
}
},
"required": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@
],
"default": null
},
"ddex_app": {
"type": [
"string",
"null"
],
"default": null
},
"track_segments": {
"type": "array",
"minItems": 0,
Expand Down Expand Up @@ -599,4 +606,4 @@
]
}
}
}
}
2 changes: 2 additions & 0 deletions packages/libs/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export type TrackMetadata = {
permalink: string
audio_upload_id: Nullable<string>
preview_start_seconds: Nullable<number>
ddex_app?: Nullable<string>

// Optional Fields
is_invalid?: boolean
Expand Down Expand Up @@ -206,4 +207,5 @@ export type CollectionMetadata = {
updated_at: string
activity_timestamp?: string
is_image_autogenerated?: boolean
ddex_app?: Nullable<string>
}
Loading