{"id":15095932,"url":"https://github.com/dieg0code/portfolio_02_lambda_api_scraper","last_synced_at":"2026-01-06T21:50:24.553Z","repository":{"id":252346461,"uuid":"840130737","full_name":"Dieg0Code/portfolio_02_lambda_api_scraper","owner":"Dieg0Code","description":"Serverless backend architecture using AWS Lambdas","archived":false,"fork":false,"pushed_at":"2024-08-19T05:47:46.000Z","size":13454,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-01T17:44:18.006Z","etag":null,"topics":["aws-lambda","chile","dynamodb","gin-gonic","golang","lambda","monorepo","scraper","serverless","terraform"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dieg0Code.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-09T03:22:40.000Z","updated_at":"2024-08-24T08:01:51.000Z","dependencies_parsed_at":"2024-12-06T07:41:03.225Z","dependency_job_id":"1f64a587-b2c4-41e7-8b04-ba95e3e9da0d","html_url":"https://github.com/Dieg0Code/portfolio_02_lambda_api_scraper","commit_stats":{"total_commits":59,"total_committers":1,"mean_commits":59.0,"dds":0.0,"last_synced_commit":"c79560fc86c267599c24e3cd55590f1a759fc63e"},"previous_names":["dieg0code/portfolio_02_lambda_api_scraper"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2Fportfolio_02_lambda_api_scraper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2Fportfolio_02_lambda_api_scraper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2Fportfolio_02_lambda_api_scraper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dieg0Code%2Fportfolio_02_lambda_api_scraper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dieg0Code","download_url":"https://codeload.github.com/Dieg0Code/portfolio_02_lambda_api_scraper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245852682,"owners_count":20683075,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-lambda","chile","dynamodb","gin-gonic","golang","lambda","monorepo","scraper","serverless","terraform"],"created_at":"2024-09-25T15:44:01.849Z","updated_at":"2026-01-06T21:50:24.492Z","avatar_url":"https://github.com/Dieg0Code.png","language":"Go","readme":"![infra](infra_p02.png)\n\n# Serverless Api-Scraper\n\nServerless API. Scrape data from a supermarket website and store it in a dynamoDB database.\n\nIts a mono-repo with the following structure:\n\n- `api` - Serverless API - Products\n- `scraper` - Serverless Scraper\n- `shared` - Shared code\n\nThe infrastructure is defined using Terraform.\n\nThe api lambda is triggered by an API Gateway and the scraper lambda is triggered by the api.\n\n- `[GET] /api/v1/products` - Get all products\n\n```json\n{\n    \"code\": 200,\n    \"status\": \"OK\",\n    \"message\": \"Success getting all products\",\n    \"data\": [\n        {\n            \"product_id\": \"uuid\",\n            \"name\": \"Producto 1\",\n            \"category\": \"category 1\",\n            \"original_price\": 899,\n            \"discounted_price\": 0\n        },\n        {\n            \"product_id\": \"uuid\",\n            \"name\": \"Producto 2\",\n            \"category\": \"category 2\",\n            \"original_price\": 999,\n            \"discounted_price\": 0\n        }\n    ]\n}\n```\n\n- `[GET] /api/v1/products/{ProductID}` - Get a product by ID\n\n```json\n{\n    \"code\": 200,\n    \"status\": \"OK\",\n    \"message\": \"Success getting product\",\n    \"data\": {\n        \"product_id\": \"uuid\",\n        \"name\": \"Producto 1\",\n        \"category\": \"category 1\",\n        \"original_price\": 899,\n        \"discounted_price\": 0\n    }\n}\n```\n\n- `[POST] /api/v1/products` - Update Data needs a token\n\n```json\n{\n    \"update_data\" : true\n}\n```\n\n```json\n{\n    \"code\": 200,\n    \"status\": \"OK\",\n    \"message\": \"Success updating data\",\n    \"data\": null\n}\n```\n\n- `[POST] /api/v1/users` - Register a user\n\n```json\n{\n    \"username\": \"username\",\n    \"email\": \"test@tes.com\",\n    \"password\": \"password\",\n    \"role\": \"admin\"\n}\n```\n\n```json\n{\n    \"code\": 200,\n    \"status\": \"OK\",\n    \"message\": \"Success registering user\",\n    \"data\": \"User username created successfully ID: uuid\"\n}\n```\n\n- `[POST] /api/v1/users/login` - Login a user\n\n```json\n{\n    \"email\": \"test@test.com\",\n    \"password\": \"password\"\n}\n```\n\n```json\n{\n    \"code\": 200,\n    \"status\": \"OK\",\n    \"message\": \"Success logging in\",\n    \"data\": \"token\"\n}\n```\n\n- `[GET] /api/v1/users` - Get all users\n\n```json\n{\n    \"code\": 200,\n    \"status\": \"OK\",\n    \"message\": \"Success getting all users\",\n    \"data\": [\n        {\n            \"user_id\": \"uuid\",\n            \"username\": \"username\",\n            \"email\": \"test@test.com\",\n        },\n        {\n            \"user_id\": \"uuid\",\n            \"username\": \"username\",\n            \"email\": \"test1@test.com\",\n        }\n    ]\n}\n```\n\n## Class Diagram - API Products\n\n```mermaid\nclassDiagram\n    direction TB\n\n    %% Interfaces en la parte superior\n    class ProductRepository {\n        \u003c\u003cinterface\u003e\u003e\n        +GetAll() []Product\n        +GetByID(id: string) Product\n    }\n\n    class ProductService {\n        \u003c\u003cinterface\u003e\u003e\n        +GetAll() []ProductResponse\n        +GetByID(productID: string) ProductResponse\n        +UpdateData(updateData: UpdateDataRequest) bool\n    }\n\n    class ProductController {\n        \u003c\u003cinterface\u003e\u003e\n        +GetAll(ctx: *gin.Context)\n        +GetByID(ctx: *gin.Context)\n        +UpdateData(ctx: *gin.Context)\n    }\n\n    %% Implementaciones en el medio\n    class ProductRepositoryImpl {\n        -dynamodbiface.DynamoDBAPI db\n        -string tableName\n        +GetAll() []Product\n        +GetByID(id: string) Product\n    }\n\n    class ProductServiceImpl {\n        -ProductRepository productRepository\n        +GetAll() []ProductResponse\n        +GetByID(productID: string) ProductResponse\n        +UpdateData(updateData: UpdateDataRequest) bool\n    }\n\n    class ProductControllerImpl {\n        -ProductService productService\n        +GetAll(ctx: *gin.Context)\n        +GetByID(ctx: *gin.Context)\n        +UpdateData(ctx: *gin.Context)\n    }\n\n    %% Clases relacionadas con productos y respuestas en la parte inferior\n    class Product {\n        +string ProductID\n        +string Name\n        +string Category\n        +int OriginalPrice\n        +int DiscountedPrice\n    }\n\n    class UpdateDataRequest {\n        +bool UpdateData\n    }\n\n    class ProductResponse {\n        +string ProductID\n        +string Name\n        +string Category\n        +int OriginalPrice\n        +int DiscountedPrice\n    }\n\n    class BaseResponse {\n        +int Code\n        +string Status\n        +string Message\n        +interface Data\n    }\n\n    %% Implementación de Interfaces\n    ProductRepositoryImpl ..|\u003e ProductRepository : implements\n    ProductServiceImpl ..|\u003e ProductService : implements\n    ProductControllerImpl ..|\u003e ProductController : implements\n\n    %% Relaciones entre clases\n    ProductResponse \u003c|-- BaseResponse : data\n    ProductRepositoryImpl o-- Product : manages\n    ProductServiceImpl o-- ProductResponse : returns\n    ProductServiceImpl o-- UpdateDataRequest : uses\n    ProductControllerImpl o-- BaseResponse : returns\n\n\n```\n\n## Class Diagram - Scraper\n\n```mermaid\nclassDiagram\n    direction TB\n\n    %% Interfaces\n    class ScraperRepository {\n        \u003c\u003cinterface\u003e\u003e\n        +Create(product models.Product) (models.Product, error)\n        +DeleteAll() error\n    }\n\n    class ScraperService {\n        \u003c\u003cinterface\u003e\u003e\n        +GetProducts() (bool, error)\n    }\n\n    class Scraper {\n        \u003c\u003cinterface\u003e\u003e\n        +CleanPrice(price string) (int, error)\n        +ScrapeData(baseURL string, maxPage int, category string) ([]models.Product, error)\n    }\n\n    %% Implementaciones\n    class ScraperRepositoryImpl {\n        -dynamodbiface.DynamoDBAPI db\n        -string tableName\n        +Create(product models.Product) (models.Product, error)\n        +DeleteAll() error\n    }\n\n    class ScraperServiceImpl {\n        -Scraper scraper.Scraper\n        -ScraperRepository scraperRepository\n        +GetProducts() (bool, error)\n    }\n\n    class ScraperImpl {\n        -colly.Collector Collector\n        +CleanPrice(price string) (int, error)\n        +ScrapeData(baseURL string, maxPage int, category string) ([]models.Product, error)\n    }\n\n    %% Clases relacionadas\n    class Product {\n        +string ProductID\n        +string Name\n        +string Category\n        +int OriginalPrice\n        +int DiscountedPrice\n    }\n\n    %% Implementación de Interfaces\n    ScraperRepositoryImpl ..|\u003e ScraperRepository : implements\n    ScraperServiceImpl ..|\u003e ScraperService : implements\n    ScraperImpl ..|\u003e Scraper : implements\n\n    %% Relaciones entre clases\n    ScraperServiceImpl --\u003e ScraperImpl : scraper\n    ScraperServiceImpl --\u003e ScraperRepositoryImpl : scraperRepository\n    ScraperRepositoryImpl --\u003e Product : manages\n    ScraperImpl --\u003e Product : returns\n\n```\n\n## Class Diagram - API Users\n\n```mermaid\nclassDiagram\n    direction TB\n\n    %% Interfaces\n    class UserRepository {\n        \u003c\u003cinterface\u003e\u003e\n        +GetAll() ([]models.User, error)\n        +GetByID(id string) (models.User, error)\n        +Create(user models.User) (models.User, error)\n        +GetByEmail(email string) (models.User, error)\n    }\n\n    class UserService {\n        \u003c\u003cinterface\u003e\u003e\n        +RegisterUser(createUserReq request.CreateUserRequest) (models.User, error)\n        +GetAllUsers() ([]response.UserResponse, error)\n        +GetUserByID(id string) (response.UserResponse, error)\n        +LogInUser(logInUserReq request.LogInUserRequest) (response.LogInUserResponse, error)\n    }\n\n    class UserController {\n        \u003c\u003cinterface\u003e\u003e\n        +RegisterUser(c *gin.Context)\n        +GetAllUsers(c *gin.Context)\n        +GetUserByID(c *gin.Context)\n        +LogInUser(c *gin.Context)\n    }\n\n    %% Implementaciones\n    class UserRepositoryImpl {\n        -dynamodbiface.DynamoDBAPI db\n        -string tableName\n        +GetAll() ([]models.User, error)\n        +GetByID(id string) (models.User, error)\n        +Create(user models.User) (models.User, error)\n        +GetByEmail(email string) (models.User, error)\n    }\n\n    class UserServiceImpl {\n        -UserRepository userRepository\n        -*validator.Validate validator\n        -utils.PasswordHasher passwordHasher\n        -utils.JWTUtils jwtUtils\n        +RegisterUser(createUserReq request.CreateUserRequest) (models.User, error)\n        +GetAllUsers() ([]response.UserResponse, error)\n        +GetUserByID(id string) (response.UserResponse, error)\n        +LogInUser(logInUserReq request.LogInUserRequest) (response.LogInUserResponse, error)\n    }\n\n    class UserControllerImpl {\n        -services.UserService userService\n        +RegisterUser(c *gin.Context)\n        +GetAllUsers(c *gin.Context)\n        +GetUserByID(c *gin.Context)\n        +LogInUser(c *gin.Context)\n    }\n\n    %% Clases relacionadas\n    class User {\n        +string UserID\n        +string Username\n        +string Email\n        +string Password\n        +string Role\n    }\n\n    class CreateUserRequest {\n        +string Username\n        +string Email\n        +string Password\n        +string Role\n    }\n\n    class LogInUserRequest {\n        +string Email\n        +string Password\n    }\n\n    class UserResponse {\n        +string UserID\n        +string Username\n        +string Email\n    }\n\n    class LogInUserResponse {\n        +string Token\n    }\n\n    class BaseResponse {\n        +int Code\n        +string Status\n        +string Message\n        +interface Data\n    }\n\n    %% Implementación de Interfaces\n    UserRepositoryImpl ..|\u003e UserRepository : implements\n    UserServiceImpl ..|\u003e UserService : implements\n    UserControllerImpl ..|\u003e UserController : implements\n\n    %% Relaciones entre clases\n    UserResponse \u003c|-- BaseResponse : data\n    LogInUserResponse \u003c|-- BaseResponse : data\n    UserRepositoryImpl o-- User : manages\n    UserServiceImpl o-- UserResponse : returns\n    UserServiceImpl o-- CreateUserRequest : uses\n    UserServiceImpl o-- LogInUserRequest : uses\n    UserControllerImpl o-- BaseResponse : returns\n```\n\n## Class Diagram - Authorizer\n\n```mermaid\nclassDiagram\n    direction TB\n\n    %% Interfaces\n    class JWTValidator {\n        \u003c\u003cinterface\u003e\u003e\n        +ValidateToken(tokenString string, secret []byte) (jwt.MapClaims, error)\n    }\n\n    class Policy {\n        \u003c\u003cinterface\u003e\u003e\n        +GeneratePolicy(principalID, effect, resource string) events.APIGatewayCustomAuthorizerResponse\n    }\n\n    class AuthorizerHandler {\n        \u003c\u003cinterface\u003e\u003e\n        +HandleAuthorizer(ctx context.Context, event events.APIGatewayCustomAuthorizerRequest) (events.APIGatewayCustomAuthorizerResponse, error)\n    }\n\n    %% Implementaciones\n    class JWTValidatorImpl {\n        +ValidateToken(tokenString string, secret []byte) (jwt.MapClaims, error)\n    }\n\n    class PolicyImpl {\n        +GeneratePolicy(principalID, effect, resource string) events.APIGatewayCustomAuthorizerResponse\n    }\n\n    class AuthorizerHandlerImpl {\n        -jwtValidator auth.JWTValidator\n        -policy aws.Policy\n        +HandleAuthorizer(ctx context.Context, event events.APIGatewayCustomAuthorizerRequest) (events.APIGatewayCustomAuthorizerResponse, error)\n    }\n\n    %% Implementación de Interfaces\n    JWTValidatorImpl ..|\u003e JWTValidator : implements\n    PolicyImpl ..|\u003e Policy : implements\n    AuthorizerHandlerImpl ..|\u003e AuthorizerHandler : implements\n\n    %% Relaciones entre clases\n    AuthorizerHandlerImpl --\u003e JWTValidatorImpl : uses\n    AuthorizerHandlerImpl --\u003e PolicyImpl : uses\n```\n\n## Interaction Diagram between Lambdas and DynamoDB\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant APIGateway\n    participant AuthorizerLambda as authorizer Lambda\n    participant UserLambda as api_users Lambda\n    participant APILambda as api_products Lambda\n    participant ScraperLambda as Scraper Lambda\n    participant DynamoDB\n\n\n    %% Register User request - response\n    User-\u003e\u003eAPIGateway: Request (Register) [POST] /api/v1/users\n    APIGateway-\u003e\u003eUserLambda: Invoke Lambda\n    UserLambda-\u003e\u003eDynamoDB: Register User\n    DynamoDB--\u003e\u003eUserLambda: Return Success\n    UserLambda--\u003e\u003eAPIGateway: Respond with Success\n    APIGateway--\u003e\u003eUser: User Created successfully\n\n    %% Login User request - response\n    User-\u003e\u003eAPIGateway: Request (Login) [POST] /api/v1/users/login\n    APIGateway-\u003e\u003eUserLambda: Invoke Lambda\n    UserLambda-\u003e\u003eDynamoDB: GetUserByEmail(email)\n    DynamoDB--\u003e\u003eUserLambda: Return User\n    UserLambda--\u003e\u003eAPIGateway: Respond with Token\n    APIGateway--\u003e\u003eUser: Return Token\n\n    %% Update Product List request - response\n    User-\u003e\u003eAPIGateway: Request (Update Product List) [POST] /api/v1/products : Token\n    APIGateway-\u003e\u003eAuthorizerLambda: Validate Token\n    AuthorizerLambda-\u003e\u003eAPIGateway: Return Success\n    APIGateway-\u003e\u003eAPILambda: Invoke Lambda\n    APILambda-\u003e\u003eScraperLambda: Trigger Scraper Lambda\n    ScraperLambda-\u003e\u003eSupermarketWebpage: Scrape Data\n    ScraperLambda-\u003e\u003eDynamoDB: Update Products\n    AuthorizerLambda--\u003e\u003eAPIGateway: Return Success\n    ScraperLambda--\u003e\u003eAPILambda: Return Success\n    APILambda--\u003e\u003eAPIGateway: Respond with Success\n    APIGateway--\u003e\u003eUser: Return Scraper Started Successfully\n    \n    %% Get All Products request - response\n    User-\u003e\u003eAPIGateway: Request (Get all products) [GET] /api/v1/products\n    APIGateway-\u003e\u003eAPILambda: Invoke Lambda\n    APILambda-\u003e\u003eDynamoDB: Query Products\n    DynamoDB--\u003e\u003eAPILambda: Return Products\n    APILambda--\u003e\u003eAPIGateway: Respond with Products\n    APIGateway--\u003e\u003eUser: List of Products\n\n    %% Get Product by ID request - response\n    User-\u003e\u003eAPIGateway: Request (Get product by ID) [GET] /api/v1/products/{ProductID}\n    APIGateway-\u003e\u003eAPILambda: Invoke Lambda\n    APILambda-\u003e\u003eDynamoDB: Get Product by ID\n    DynamoDB--\u003e\u003eAPILambda: Return Product\n    APILambda--\u003e\u003eAPIGateway: Respond with Product\n    APIGateway--\u003e\u003eUser: Return Product\n\n    %% Get All Users request - response\n    User-\u003e\u003eAPIGateway: Request (Get all users) [GET] /api/v1/users\n    APIGateway-\u003e\u003eUserLambda: Invoke Lambda\n    UserLambda-\u003e\u003eDynamoDB: Get All Users\n    DynamoDB--\u003e\u003eUserLambda: Return Users\n    UserLambda--\u003e\u003eAPIGateway: Respond with Users\n    APIGateway--\u003e\u003eUser: Return Users\n\n    %% Get User by ID request - response\n    User-\u003e\u003eAPIGateway: Request (Get user by ID) [GET] /api/v1/users/{UserID}\n    APIGateway-\u003e\u003eUserLambda: Invoke Lambda\n    UserLambda-\u003e\u003eDynamoDB: Get User by ID\n    DynamoDB--\u003e\u003eUserLambda: Return User\n    UserLambda--\u003e\u003eAPIGateway: Respond with User\n    APIGateway--\u003e\u003eUser: Return User\n```\n\n## CI/CD Pipeline\n\n```mermaid\ngraph TD\n    A[Push to main branch] --\u003e|Trigger| B[CI/CD Pipeline]\n    B --\u003e C[Test and Build API]\n    B --\u003e F[Test and Build API Users]\n    \n    subgraph \"Test and Build API\"\n    C --\u003e C1[Checkout code]\n    C1 --\u003e C2[Set up Go]\n    C2 --\u003e C3[Sync modules]\n    C3 --\u003e C4[Cache dependencies]\n    C4 --\u003e C5[Install dependencies]\n    C5 --\u003e C6[Run golangci-lint]\n    C6 --\u003e C7[Run tests]\n    C7 --\u003e C8[Upload coverage to codecov]\n    C8 --\u003e C9[Build API binary]\n    C9 --\u003e C10[Zip API binary]\n    C10 --\u003e C11[Upload API artifact]\n    end\n\n    C11 --\u003e|Trigger| D[Test and Build Scraper]\n    \n    subgraph \"Test and Build Scraper\"\n    D --\u003e D1[Checkout code]\n    D1 --\u003e D2[Set up Go]\n    D2 --\u003e D3[Cache dependencies]\n    D3 --\u003e D4[Install dependencies]\n    D4 --\u003e D5[Run golangci-lint]\n    D5 --\u003e D6[Run tests]\n    D6 --\u003e D7[Upload coverage to codecov]\n    D7 --\u003e D8[Build Scraper binary]\n    D8 --\u003e D9[Zip Scraper binary]\n    D9 --\u003e D10[Upload Scraper artifact]\n    end\n\n    subgraph \"Test and Build API Users\"\n    F --\u003e F1[Checkout code]\n    F1 --\u003e F2[Set up Go]\n    F2 --\u003e F3[Cache dependencies]\n    F3 --\u003e F4[Install dependencies]\n    F4 --\u003e F5[Run golangci-lint]\n    F5 --\u003e F6[Run tests]\n    F6 --\u003e F7[Upload coverage to codecov]\n    F7 --\u003e F8[Build API Users binary]\n    F8 --\u003e F9[Zip API Users binary]\n    F9 --\u003e F10[Upload API Users artifact]\n    end\n\n    F10 --\u003e|Trigger| G[Test and Build Authorizer]\n\n    subgraph \"Test and Build Authorizer\"\n    G --\u003e G1[Checkout code]\n    G1 --\u003e G2[Set up Go]\n    G2 --\u003e G3[Cache dependencies]\n    G3 --\u003e G4[Install dependencies]\n    G4 --\u003e G5[Run golangci-lint]\n    G5 --\u003e G6[Run tests]\n    G6 --\u003e G7[Upload coverage to codecov]\n    G7 --\u003e G8[Build Authorizer binary]\n    G8 --\u003e G9[Zip Authorizer binary]\n    G9 --\u003e G10[Upload Authorizer artifact]\n    end\n    \n    D10 --\u003e|Trigger| E[Deploy]\n    G10 --\u003e|Trigger| E[Deploy]\n    \n    subgraph \"Deploy\"\n    E --\u003e E1[Checkout code]\n    E1 --\u003e E2[Download API artifact]\n    E2 --\u003e E3[Download Scraper artifact]\n    E3 --\u003e E4[Download API Users artifact]\n    E4 --\u003e E5[Download Authorizer artifact]\n    E5 --\u003e E6[Set up Terraform]\n    E6 --\u003e E7[Initialize Terraform]\n    E7 --\u003e E8[Plan Terraform]\n    E8 --\u003e E9[Apply Terraform]\n    end\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdieg0code%2Fportfolio_02_lambda_api_scraper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdieg0code%2Fportfolio_02_lambda_api_scraper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdieg0code%2Fportfolio_02_lambda_api_scraper/lists"}