zenjoul80 commited on
Commit
78ce901
Β·
verified Β·
1 Parent(s): 37c1305

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -73
app.py CHANGED
@@ -1,102 +1,81 @@
1
- import time, requests, threading, io
2
- from flask import Flask, render_template, request, session, send_file, jsonify
3
  from flask_socketio import SocketIO, emit
4
 
5
  app = Flask(__name__)
6
- app.config['SECRET_KEY'] = 'suno_studio_2026'
7
- # Optimized for Hugging Face proxying
8
- socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')
9
 
10
- BASE_URL = "https://api.sunoapi.org/api/v1"
 
 
 
 
 
 
11
 
12
  @app.route('/')
13
  def index():
14
  return render_template('index.html')
15
 
 
16
  @app.route('/callback', methods=['POST'])
17
  def callback():
18
- """Receives completion data from Suno."""
19
  data = request.json
20
  task_id = data.get('taskId') or data.get('task_id')
21
  audio_url = data.get('audio_url')
22
-
23
- if audio_url:
24
- socketio.emit('status', {
25
- 'msg': 'βœ… Webhook: Track Ready!',
26
- 'url': audio_url,
27
- 'done': True
28
- })
29
- return jsonify({"status": "received"}), 200
30
 
31
- @app.route('/download_proxy')
32
- def download_proxy():
33
- """Bypasses CORS to force download the MP3 file."""
34
- url = request.args.get('url')
35
- title = request.args.get('title', 'Suno_Track').replace(" ", "_")
36
- try:
37
- res = requests.get(url, stream=True)
38
- res.raise_for_status()
39
- return send_file(
40
- io.BytesIO(res.content),
41
- mimetype="audio/mpeg",
42
- as_attachment=True,
43
- download_name=f"{title}.mp3"
44
- )
45
- except Exception as e:
46
- return f"Download Error: {str(e)}", 500
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  @socketio.on('save_token')
49
  def save_token(data):
50
- token = data.get('token')
51
- if token:
52
- session['api_token'] = token
53
- emit('status', {'msg': 'πŸ”‘ Token linked successfully.'})
54
- # Auto-check credits
55
- try:
56
- res = requests.get(f"{BASE_URL}/generate/credit", headers={"Authorization": f"Bearer {token}"})
57
- emit('credits', {'val': res.json().get('data', 0)})
58
- except: pass
59
 
60
  @socketio.on('start_gen')
61
  def handle_gen(payload):
62
  token = session.get('api_token')
63
- if not token:
64
- emit('status', {'msg': '❌ Error: No Token Connected.'})
65
- return
66
-
67
  headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
68
- sid = request.sid
69
-
 
 
70
  try:
71
- # Note: 'callBackUrl' is already in the payload from the frontend
72
- res = requests.post(f"{BASE_URL}/generate/upload-cover", json=payload, headers=headers)
73
  res_data = res.json()
 
74
 
75
- if res.status_code == 200 and res_data.get('data'):
76
- task_id = res_data['data'].get('taskId')
77
- emit('status', {'msg': f'πŸš€ Task {task_id} initiated. Processing...'})
78
- # Threaded backup polling in case callback fails
79
- threading.Thread(target=poll_status, args=(task_id, sid, headers)).start()
80
- else:
81
- emit('status', {'msg': f"❌ API Error: {res_data.get('msg', 'Unknown')}"})
82
  except Exception as e:
83
- emit('status', {'msg': f"❌ System Error: {str(e)}"})
84
-
85
- def poll_status(task_id, sid, headers):
86
- """Checks status every 12 seconds as a backup."""
87
- for _ in range(50):
88
- time.sleep(12)
89
- try:
90
- res = requests.get(f"{BASE_URL}/suno/cover/record-info?taskId={task_id}", headers=headers)
91
- data = res.json().get('data', {})
92
- if data.get('status') == 'complete':
93
- socketio.emit('status', {
94
- 'msg': '✨ Polling: Track Ready!',
95
- 'url': data.get('audio_url'),
96
- 'done': True
97
- }, room=sid)
98
- break
99
- except: break
100
 
101
  if __name__ == '__main__':
102
- socketio.run(app, host="0.0.0.0", allow_unsafe_werkzeug=True)
 
1
+ import time, requests, threading, os, io
2
+ from flask import Flask, render_template, request, session, send_from_directory, jsonify
3
  from flask_socketio import SocketIO, emit
4
 
5
  app = Flask(__name__)
6
+ app.config['SECRET_KEY'] = 'server_direct_save_2026'
7
+ socketio = SocketIO(app, cors_allowed_origins="*")
 
8
 
9
+ # Create a permanent folder on the server for the music
10
+ MUSIC_FOLDER = 'saved_music'
11
+ if not os.path.exists(MUSIC_FOLDER):
12
+ os.makedirs(MUSIC_FOLDER)
13
+
14
+ # Map to link taskIds to User Session IDs (for the callback)
15
+ task_to_sid = {}
16
 
17
  @app.route('/')
18
  def index():
19
  return render_template('index.html')
20
 
21
+ # 1. THE CALLBACK (Saves the file to server storage)
22
  @app.route('/callback', methods=['POST'])
23
  def callback():
 
24
  data = request.json
25
  task_id = data.get('taskId') or data.get('task_id')
26
  audio_url = data.get('audio_url')
 
 
 
 
 
 
 
 
27
 
28
+ if audio_url and task_id:
29
+ # Download the file to the server immediately
30
+ filename = f"{task_id}.mp3"
31
+ filepath = os.path.join(MUSIC_FOLDER, filename)
32
+
33
+ try:
34
+ r = requests.get(audio_url)
35
+ with open(filepath, 'wb') as f:
36
+ f.write(r.content)
37
+
38
+ # Find the user who owns this task and tell them
39
+ if task_id in task_to_sid:
40
+ user_sid = task_to_sid[task_id]
41
+ socketio.emit('status', {
42
+ 'msg': 'βœ… Saved to Server!',
43
+ 'file_name': filename,
44
+ 'done': True
45
+ }, room=user_sid)
46
+ except Exception as e:
47
+ print(f"Callback save error: {e}")
48
+
49
+ return jsonify({"status": "ok"}), 200
50
+
51
+ # 2. THE DIRECT DOWNLOAD (Serves the file from your server)
52
+ @app.route('/get_music/<filename>')
53
+ def get_music(filename):
54
+ return send_from_directory(MUSIC_FOLDER, filename, as_attachment=True)
55
 
56
  @socketio.on('save_token')
57
  def save_token(data):
58
+ session['api_token'] = data.get('token')
59
+ emit('status', {'msg': 'πŸ”‘ Token Linked.'})
 
 
 
 
 
 
 
60
 
61
  @socketio.on('start_gen')
62
  def handle_gen(payload):
63
  token = session.get('api_token')
 
 
 
 
64
  headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
65
+
66
+ # Set the callback URL dynamically
67
+ payload['callBackUrl'] = request.host_url + "callback"
68
+
69
  try:
70
+ res = requests.post("https://api.sunoapi.org/api/v1/generate/upload-cover", json=payload, headers=headers)
 
71
  res_data = res.json()
72
+ task_id = res_data.get('data', {}).get('taskId')
73
 
74
+ if task_id:
75
+ task_to_sid[task_id] = request.sid # Map user to task
76
+ emit('status', {'msg': f'πŸš€ Processing Task: {task_id}...'})
 
 
 
 
77
  except Exception as e:
78
+ emit('status', {'msg': f'❌ Error: {str(e)}'})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
  if __name__ == '__main__':
81
+ socketio.run(app, host="0.0.0.0")