Main coves client
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(api): add listCommunities and createPost endpoints

Add CovesApiService methods for community operations:
- listCommunities(): Fetch communities with pagination and sorting
- createPost(): Create posts with title, content, embeds, and labels

Both methods include proper error handling and debug logging.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

+126
+126
lib/services/coves_api_service.dart
··· 3 3 4 4 import '../config/environment_config.dart'; 5 5 import '../models/comment.dart'; 6 + import '../models/community.dart'; 6 7 import '../models/post.dart'; 7 8 import 'api_exceptions.dart'; 8 9 ··· 355 356 debugPrint('❌ Error parsing comments response: $e'); 356 357 } 357 358 throw ApiException('Failed to parse server response', originalError: e); 359 + } 360 + } 361 + 362 + /// List communities with optional filtering 363 + /// 364 + /// Fetches a list of communities with pagination support. 365 + /// Requires authentication. 366 + /// 367 + /// Parameters: 368 + /// - [limit]: Number of communities per page (default: 50, max: 100) 369 + /// - [cursor]: Pagination cursor from previous response 370 + /// - [sort]: Sort order - 'popular', 'new', or 'alphabetical' (default: 'popular') 371 + Future<CommunitiesResponse> listCommunities({ 372 + int limit = 50, 373 + String? cursor, 374 + String sort = 'popular', 375 + }) async { 376 + try { 377 + if (kDebugMode) { 378 + debugPrint('📡 Fetching communities: sort=$sort, limit=$limit'); 379 + } 380 + 381 + final queryParams = <String, dynamic>{ 382 + 'limit': limit, 383 + 'sort': sort, 384 + }; 385 + 386 + if (cursor != null) { 387 + queryParams['cursor'] = cursor; 388 + } 389 + 390 + final response = await _dio.get( 391 + '/xrpc/social.coves.community.list', 392 + queryParameters: queryParams, 393 + ); 394 + 395 + if (kDebugMode) { 396 + debugPrint( 397 + '✅ Communities fetched: ' 398 + '${response.data['communities']?.length ?? 0} communities', 399 + ); 400 + } 401 + 402 + return CommunitiesResponse.fromJson( 403 + response.data as Map<String, dynamic>, 404 + ); 405 + } on DioException catch (e) { 406 + _handleDioException(e, 'communities'); 407 + } catch (e) { 408 + if (kDebugMode) { 409 + debugPrint('❌ Error parsing communities response: $e'); 410 + } 411 + throw ApiException('Failed to parse server response', originalError: e); 412 + } 413 + } 414 + 415 + /// Create a new post in a community 416 + /// 417 + /// Creates a new post with optional title, content, and embed. 418 + /// Requires authentication. 419 + /// 420 + /// Parameters: 421 + /// - [community]: Community identifier (required) 422 + /// - [title]: Post title (optional) 423 + /// - [content]: Post content (optional) 424 + /// - [embed]: External embed (link, image, etc.) (optional) 425 + /// - [langs]: Language codes for the post (optional) 426 + /// - [labels]: Self-applied content labels (optional) 427 + Future<CreatePostResponse> createPost({ 428 + required String community, 429 + String? title, 430 + String? content, 431 + ExternalEmbedInput? embed, 432 + List<String>? langs, 433 + SelfLabels? labels, 434 + }) async { 435 + try { 436 + if (kDebugMode) { 437 + debugPrint('📡 Creating post in community: $community'); 438 + } 439 + 440 + // Build request body with only non-null fields 441 + final requestBody = <String, dynamic>{ 442 + 'community': community, 443 + }; 444 + 445 + if (title != null) { 446 + requestBody['title'] = title; 447 + } 448 + 449 + if (content != null) { 450 + requestBody['content'] = content; 451 + } 452 + 453 + if (embed != null) { 454 + requestBody['embed'] = embed.toJson(); 455 + } 456 + 457 + if (langs != null && langs.isNotEmpty) { 458 + requestBody['langs'] = langs; 459 + } 460 + 461 + if (labels != null) { 462 + requestBody['labels'] = labels.toJson(); 463 + } 464 + 465 + final response = await _dio.post( 466 + '/xrpc/social.coves.community.post.create', 467 + data: requestBody, 468 + ); 469 + 470 + if (kDebugMode) { 471 + debugPrint('✅ Post created successfully'); 472 + } 473 + 474 + return CreatePostResponse.fromJson( 475 + response.data as Map<String, dynamic>, 476 + ); 477 + } on DioException catch (e) { 478 + _handleDioException(e, 'create post'); 479 + } catch (e) { 480 + if (kDebugMode) { 481 + debugPrint('❌ Error creating post: $e'); 482 + } 483 + throw ApiException('Failed to create post', originalError: e); 358 484 } 359 485 } 360 486