├── how-to-get-token.png ├── src ├── main │ └── java │ │ └── com │ │ └── pkslow │ │ └── ai │ │ ├── domain │ │ ├── AnswerStatus.java │ │ ├── BardResponse.java │ │ ├── Answer.java │ │ ├── Image.java │ │ └── BardRequest.java │ │ ├── AIClient.java │ │ ├── util │ │ ├── NetworkUtils.java │ │ ├── WebUtils.java │ │ ├── Constants.java │ │ └── BardUtils.java │ │ ├── GoogleBardExample.java │ │ └── GoogleBardClient.java └── test │ ├── java │ └── com │ │ └── pkslow │ │ └── ai │ │ ├── util │ │ ├── NetworkUtilsTest.java │ │ ├── WebUtilsTest.java │ │ └── BardUtilsTest.java │ │ ├── domain │ │ └── PojoTest.java │ │ └── GoogleBardClientTest.java │ └── resources │ ├── answer-response-body-no-image.json │ ├── answer-response-body-with-image.json │ └── answer-response-body-multiple-images.json ├── .gitignore ├── LICENSE ├── .github └── workflows │ └── maven.yml ├── README.md └── pom.xml /how-to-get-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LarryDpk/Google-Bard/HEAD/how-to-get-token.png -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/domain/AnswerStatus.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.domain; 2 | 3 | public enum AnswerStatus { 4 | OK, 5 | NO_ANSWER, 6 | ERROR, 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/AIClient.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai; 2 | 3 | 4 | import com.pkslow.ai.domain.Answer; 5 | 6 | public interface AIClient { 7 | Answer ask(String question); 8 | void reset(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/domain/BardResponse.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @AllArgsConstructor 7 | @Getter 8 | public class BardResponse { 9 | private final String conversationId; 10 | private final String responseId; 11 | private final String choiceId; 12 | private final Answer answer; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/util/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.util; 2 | 3 | public class NetworkUtils { 4 | public static void setUpProxy(String host, String port) { 5 | System.setProperty("http.proxyHost", host); 6 | System.setProperty("http.proxyPort", port); 7 | System.setProperty("https.proxyHost", host); 8 | System.setProperty("https.proxyPort", port); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | .idea 26 | target 27 | 28 | .DS_Store -------------------------------------------------------------------------------- /src/test/java/com/pkslow/ai/util/NetworkUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.util; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class NetworkUtilsTest { 7 | @Test 8 | public void setProxy() { 9 | NetworkUtils.setUpProxy("www.pkslow.com", "8080"); 10 | Assert.assertEquals(System.getProperty("https.proxyHost"), "www.pkslow.com"); 11 | Assert.assertEquals(System.getProperty("https.proxyPort"), "8080"); 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/com/pkslow/ai/util/WebUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.util; 2 | 3 | import okhttp3.OkHttpClient; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | import java.time.Duration; 8 | 9 | public class WebUtilsTest { 10 | @Test 11 | public void createOKHttpClient() { 12 | OkHttpClient okHttpClient = WebUtils.okHttpClientWithTimeout(Duration.ofMinutes(10)); 13 | Assert.assertNotNull(okHttpClient); 14 | int timeout = okHttpClient.callTimeoutMillis(); 15 | Assert.assertEquals(10 * 60 * 1000, timeout); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/util/WebUtils.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.util; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import okhttp3.OkHttpClient; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.time.Duration; 8 | 9 | @Slf4j 10 | public class WebUtils { 11 | @NotNull 12 | public static OkHttpClient okHttpClientWithTimeout(Duration timeout) { 13 | log.info("Creating OkHttpClient with timeout {}", timeout); 14 | OkHttpClient client = new OkHttpClient.Builder() 15 | .callTimeout(timeout) 16 | .readTimeout(timeout) 17 | .connectTimeout(timeout) 18 | .build(); 19 | log.info("OkHttpClient created"); 20 | return client; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/domain/Answer.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Getter; 6 | import lombok.ToString; 7 | 8 | import java.util.List; 9 | 10 | @AllArgsConstructor 11 | @Getter 12 | @Builder 13 | @ToString 14 | public class Answer { 15 | private final AnswerStatus status; 16 | 17 | private final String chosenAnswer; 18 | 19 | private final List images; 20 | 21 | public String markdown() { 22 | 23 | String markdown = this.chosenAnswer; 24 | 25 | if (images != null && images.size() > 0) { 26 | for (Image image : images) { 27 | markdown = markdown.replaceFirst(image.labelRegex(), image.markdown()); 28 | } 29 | 30 | } 31 | 32 | return markdown; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/domain/Image.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | @AllArgsConstructor 8 | @Getter 9 | @ToString 10 | public class Image { 11 | private final String url; 12 | private final String label; 13 | private final String article; 14 | 15 | public String markdown() { 16 | StringBuilder sb = new StringBuilder(); 17 | sb.append("\n"); 18 | sb.append("[!"); 19 | sb.append(label); 20 | sb.append("("); 21 | sb.append(url); 22 | sb.append(")]("); 23 | sb.append(article); 24 | sb.append(")"); 25 | 26 | return sb.toString(); 27 | } 28 | 29 | public String labelRegex() { 30 | String temp = label.substring(1, label.length() -1); 31 | 32 | return "\\[" + temp + "\\]"; 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/util/Constants.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.util; 2 | 3 | public class Constants { 4 | public static final String HOSTNAME = "bard.google.com"; 5 | public static final String BASE_URL = "https://bard.google.com/"; 6 | 7 | public static final String ASK_QUESTION_PATH = "_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate"; 8 | public static final String CONTENT_TYPE = "application/x-www-form-urlencoded;charset=UTF-8"; 9 | public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36"; 10 | public static final String TOKEN_COOKIE_1PSID = "__Secure-1PSID"; 11 | public static final String TOKEN_COOKIE_1PSIDTS = "__Secure-1PSIDTS"; 12 | public static final String BARD_VERSION = "boq_assistant-bard-web-server_20230808.09_p0"; 13 | 14 | public static final String EMPTY_STRING = ""; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/GoogleBardExample.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai; 2 | 3 | import com.pkslow.ai.domain.Answer; 4 | import com.pkslow.ai.domain.AnswerStatus; 5 | import com.pkslow.ai.util.NetworkUtils; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.time.Duration; 9 | 10 | @Slf4j 11 | public class GoogleBardExample { 12 | public static void main(String[] args) { 13 | NetworkUtils.setUpProxy("localhost", "7890"); 14 | String token = args[0]; 15 | AIClient client = new GoogleBardClient(token, Duration.ofMinutes(10)); 16 | 17 | printChosenAnswer(client.ask("Can you show me a picture of Pumpkin?\n How about cat?")); 18 | } 19 | 20 | private static void printChosenAnswer(Answer answer) { 21 | if (answer.getStatus() == AnswerStatus.OK) { 22 | log.info("Markdown Output: \n {}", answer.markdown()); 23 | } else { 24 | log.info("No Answer: {}", answer); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Larry Deng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test/resources/answer-response-body-no-image.json: -------------------------------------------------------------------------------- 1 | )]}' 2 | 3 | 1087 4 | [["wrb.fr",null,"[null,[\"c_b058c1fd672d48e2\",\"r_b058c1fd672d4be7\"],[[\"date today\",1],[\"Is it 365 day today?\",4]],null,[[\"rc_b058c1fd672d4b00\",[\"As of today, June 28, 2023, it is Wednesday.\"],[],null,null,null,true,null,[2],\"en\",null,null,[null,null,null,null,null,[[]]]],[\"rc_b058c1fd672d4e05\",[\"Today is Wednesday, June 28, 2023.\"],[],null,null,null,true,null,[2],\"en\",null,null,[null,null,null,null,null,[[]]]]],[\"Taipei City, Taiwan\",\"SWML_DESCRIPTION_FROM_YOUR_INTERNET_ADDRESS\",false,[[[null,null,null,[[300,200],null,null,[[238409460,1202498071],[262249812,1228810465]]]]],[[2,null,null,null,null,[null,null,null,[[[250329636,1215654268],149558.5,1931574222,1,864863983]]]]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[null,null,null,null,null,null,null,true]],\"//www.google.com/maps/vt/data\\u003deSECivSzAZXGnSDQAIOOdl76QwyRlhDY31AVwnGv_8dLjgTo2Z8AR1V74VJ1wn1pwc5l-Iwt3Avli4wqxVpzG7hwCFbeCIFkUYpjXl6nBrO6cTliWqQ2-_4OHPISz6WWE3DQSj3ZmtUJQvNm9fd2zF6kHPH6lW5xF3tX1lMYg_FyH34QLzDYjcc6q6N_Zg\"],null,null,\"TW\"]"]] 5 | 58 6 | [["di",3958],["af.httprm",3957,"8211027492107473526",5]] 7 | 26 8 | [["e",4,null,null,1185]] 9 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Java CI with Maven 10 | 11 | on: 12 | push: 13 | branches: [ "main" ] 14 | pull_request: 15 | branches: [ "main" ] 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v3 24 | - name: Set up JDK 8 25 | uses: actions/setup-java@v3 26 | with: 27 | java-version: '8' 28 | distribution: 'temurin' 29 | cache: maven 30 | - name: Build with Maven 31 | run: mvn -B verify --file pom.xml 32 | 33 | # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive 34 | - name: Update dependency graph 35 | uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 36 | -------------------------------------------------------------------------------- /src/test/java/com/pkslow/ai/domain/PojoTest.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.domain; 2 | 3 | import org.junit.Test; 4 | import pl.pojo.tester.api.assertion.Method; 5 | 6 | import static pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsForAll; 7 | 8 | public class PojoTest { 9 | @Test 10 | public void testPojo() { 11 | assertPojoMethodsForAll(BardRequest.class) 12 | .quickly() 13 | .testing(Method.CONSTRUCTOR) 14 | .testing(Method.GETTER) 15 | .testing(Method.SETTER) 16 | .testing(Method.EQUALS) 17 | .testing(Method.HASH_CODE) 18 | .testing(Method.TO_STRING) 19 | .areWellImplemented(); 20 | 21 | assertPojoMethodsForAll(BardResponse.class) 22 | .quickly() 23 | .testing(Method.CONSTRUCTOR) 24 | .testing(Method.GETTER) 25 | // .testing(Method.SETTER) 26 | // .testing(Method.EQUALS) 27 | // .testing(Method.HASH_CODE) 28 | // .testing(Method.TO_STRING) 29 | .areWellImplemented(); 30 | 31 | assertPojoMethodsForAll(Answer.class) 32 | .quickly() 33 | .testing(Method.CONSTRUCTOR) 34 | .testing(Method.GETTER) 35 | .testing(Method.TO_STRING) 36 | .areWellImplemented(); 37 | 38 | assertPojoMethodsForAll(Image.class) 39 | .quickly() 40 | .testing(Method.CONSTRUCTOR) 41 | .testing(Method.GETTER) 42 | .testing(Method.TO_STRING) 43 | .areWellImplemented(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/domain/BardRequest.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.util.Objects; 8 | 9 | import static com.pkslow.ai.util.Constants.EMPTY_STRING; 10 | 11 | @AllArgsConstructor 12 | @Getter 13 | @Setter 14 | public class BardRequest { 15 | private String strSNlM0e; 16 | private String question; 17 | private String conversationId; 18 | private String responseId; 19 | private String choiceId; 20 | 21 | @Override 22 | public boolean equals(Object o) { 23 | if (this == o) return true; 24 | if (o == null || getClass() != o.getClass()) return false; 25 | BardRequest that = (BardRequest) o; 26 | return strSNlM0e.equals(that.strSNlM0e) && 27 | question.equals(that.question) && 28 | conversationId.equals(that.conversationId) && 29 | responseId.equals(that.responseId) && 30 | choiceId.equals(that.choiceId); 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | return Objects.hash(strSNlM0e, question, conversationId, responseId, choiceId); 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "BardRequest{" + 41 | "strSNlM0e=" + strSNlM0e + 42 | ", question=" + question + 43 | ", conversationId=" + conversationId + 44 | ", responseId=" + responseId + 45 | ", choiceId=" + choiceId + 46 | '}'; 47 | } 48 | 49 | public static BardRequest newEmptyBardRequest() { 50 | return new BardRequest(EMPTY_STRING, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING, EMPTY_STRING); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/resources/answer-response-body-with-image.json: -------------------------------------------------------------------------------- 1 | )]}' 2 | 3 | 3844 4 | [["wrb.fr",null,"[[\"Sure, here is a picture of Google headquarters.\\n[Image of Google headquarters]\"],[\"c_a5a3933f1102fb1e\",\"r_33687685b9931327\"],[[\"google picture\",1],[\"How do I Google an image on Google?\",4],[\"How to use Google photo?\",4]],[],[[\"rc_33687685b9931468\",[\"Sure, here is a picture of Google headquarters.\\n[Image of Google headquarters]\"],[],null,[[[[\"https://upload.wikimedia.org/wikipedia/commons/3/32/Googleplex_HQ_%28cropped%29.jpg\"],null,3024,2212,\"Google headquarters\",\"https://www.google.com/imgres?imgurl\\u003dhttps://upload.wikimedia.org/wikipedia/commons/3/32/Googleplex_HQ_%2528cropped%2529.jpg\\u0026imgrefurl\\u003dhttps://en.wikipedia.org/wiki/Googleplex\\u0026tbnid\\u003dIl8qZswZvSF4AM\\u0026docid\\u003dT_G4tXC5VtHQLM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://en.wikipedia.org/wiki/Googleplex\"],\"Wikipedia\",1,\"https://encrypted-tbn2.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcTGo2ldWXblVJVy9av_nsZSibxa_2qWNauc-_aN3Z88QWRlrBwOirgky4S2BQx4HAP717l1X6fwOGXal25Xka-QwL048XUpux7h5g\"],\"[Image of Google headquarters]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_xSJAY7HCsMwFTOL8gO22VwVBUGULJWWr0P7WWq21Onn6m1LDWEJRXr5masyK55GZHOpdSPu3QRo6bMq_B_UDo5xHKj9Rytr2F2CGxFmeBhLeKhq2O-pCcU26pFktTXfyF0Am0dkLfMFasXpLOQmqbDb5X6pAQ\\u003dw250-h200-p\"],null,263,192],0]],null,true],[\"rc_33687685b99313fd\",[\"Sure, here is an image of Google's headquarters in Mountain View, California.\\n[Image of Google headquarters in Mountain View]\"],[],null,[[[[\"https://static.dezeen.com/uploads/2017/03/google-campus-big-architecture-news-offices_dezeen_1704_hero.jpg\"],null,1704,958,\"Google headquarters in Mountain View\",\"https://www.google.com/imgres?imgurl\\u003dhttps://static.dezeen.com/uploads/2017/03/google-campus-big-architecture-news-offices_dezeen_1704_hero.jpg\\u0026imgrefurl\\u003dhttps://www.dezeen.com/2017/03/03/google-mountain-view-california-office-campus-hq-big-bjarke-ingels-thomas-heatherwick-studio/\\u0026tbnid\\u003dZaET5ZryABDtpM\\u0026docid\\u003d0KsFEDeVtTBWHM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.dezeen.com/2017/03/03/google-mountain-view-california-office-campus-hq-big-bjarke-ingels-thomas-heatherwick-studio/\"],\"Dezeen\",1,\"https://encrypted-tbn0.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSs1KlvvQbshKm_av_lPiIu6wyWHGisO53Q4DpyKm9XmSyngm2dPYgBC1xjUunS_kvj0ZDCJA1prTUju0ZFF6DpgctNgiw7OWY\"],\"[Image of Google headquarters in Mountain View]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_y1qEzJD6RBdM4sJeDYMijzgVwAmLeh1eDmPHDbWXYOx5ytWSPw-LKDQrlwYk_xeXlrTWaMxjw_aN_SXSjAuwAb4ojOyDbD_fxc-a_WVQpLuIwx8furXBM4N3CbZkqtPA4Y_G94WBM_QVAg3YopTIy9RybaRT425Hs4A1RQLolzh83-g1YJignviQAWzko\\u003dw250-h200-p\"],null,300,168],0]],null,true],[\"rc_33687685b9931392\",[\"Sure, here is a picture of Google's headquarters.\\n[Image of Google headquarters]\"],[],null,[[[[\"https://upload.wikimedia.org/wikipedia/commons/3/32/Googleplex_HQ_%28cropped%29.jpg\"],null,3024,2212,\"Google headquarters\",\"https://www.google.com/imgres?imgurl\\u003dhttps://upload.wikimedia.org/wikipedia/commons/3/32/Googleplex_HQ_%2528cropped%2529.jpg\\u0026imgrefurl\\u003dhttps://en.wikipedia.org/wiki/Googleplex\\u0026tbnid\\u003dIl8qZswZvSF4AM\\u0026docid\\u003dT_G4tXC5VtHQLM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://en.wikipedia.org/wiki/Googleplex\"],\"Wikipedia\",1,\"https://encrypted-tbn2.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcTGo2ldWXblVJVy9av_nsZSibxa_2qWNauc-_aN3Z88QWRlrBwOirgky4S2BQx4HAP717l1X6fwOGXal25Xka-QwL048XUpux7h5g\"],\"[Image of Google headquarters]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_xSJAY7HCsMwFTOL8gO22VwVBUGULJWWr0P7WWq21Onn6m1LDWEJRXr5masyK55GZHOpdSPu3QRo6bMq_B_UDo5xHKj9Rytr2F2CGxFmeBhLeKhq2O-pCcU26pFktTXfyF0Am0dkLfMFasXpLOQmqbDb5X6pAQ\\u003dw250-h200-p\"],null,263,192],0]],null,true]]]"]] 5 | 57 6 | [["di",6278],["af.httprm",6279,"997198837650946186",0]] 7 | 26 8 | [["e",4,null,null,3941]] 9 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/GoogleBardClient.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai; 2 | 3 | import com.pkslow.ai.domain.Answer; 4 | import com.pkslow.ai.domain.AnswerStatus; 5 | import com.pkslow.ai.domain.BardRequest; 6 | import com.pkslow.ai.domain.BardResponse; 7 | import lombok.extern.slf4j.Slf4j; 8 | import okhttp3.*; 9 | 10 | import java.io.IOException; 11 | import java.time.Duration; 12 | import java.util.*; 13 | 14 | import static com.pkslow.ai.util.BardUtils.*; 15 | import static com.pkslow.ai.util.Constants.EMPTY_STRING; 16 | import static com.pkslow.ai.util.WebUtils.okHttpClientWithTimeout; 17 | 18 | @Slf4j 19 | public class GoogleBardClient implements AIClient { 20 | private final String token; 21 | private final OkHttpClient httpClient; 22 | private final BardRequest bardRequest = BardRequest.newEmptyBardRequest(); 23 | 24 | public GoogleBardClient(String token) { 25 | this(token, Duration.ofMinutes(5)); 26 | } 27 | 28 | public GoogleBardClient(String token, Duration timeout) { 29 | this.token = token; 30 | this.httpClient = okHttpClientWithTimeout(timeout); 31 | } 32 | 33 | public GoogleBardClient(String token, OkHttpClient httpClient) { 34 | this.token = token; 35 | this.httpClient = httpClient; 36 | } 37 | 38 | @Override 39 | public Answer ask(String question) { 40 | 41 | //Fix for multiline HTTP requests 42 | question = question.replaceAll("\\s+"," "); 43 | 44 | try { 45 | if (isEmpty(bardRequest.getStrSNlM0e())) { 46 | String strSNlM0e = callBardToGetSNlM0e(); 47 | if (isEmpty(strSNlM0e)) { 48 | throw new RuntimeException("Failed to get SNlM0e, it may be token issue"); 49 | } 50 | bardRequest.setStrSNlM0e(strSNlM0e); 51 | } 52 | 53 | bardRequest.setQuestion(question); 54 | return processAskResult(callBardToAsk(bardRequest)); 55 | } catch (Throwable e) { 56 | log.error("Failed to get answer: ", e); 57 | return Answer.builder().status(AnswerStatus.ERROR).build(); 58 | } 59 | } 60 | 61 | @Override 62 | public void reset() { 63 | bardRequest.setStrSNlM0e(EMPTY_STRING); 64 | bardRequest.setConversationId(EMPTY_STRING); 65 | bardRequest.setResponseId(EMPTY_STRING); 66 | bardRequest.setChoiceId(EMPTY_STRING); 67 | } 68 | 69 | private String callBardToGetSNlM0e() { 70 | Call call = this.httpClient.newCall(createRequestForSNlM0e(token)); 71 | try { 72 | try (Response response = call.execute()) { 73 | log.info("getSNlM0e Response code: " + response.code()); 74 | return fetchSNlM0eFromBody(Objects.requireNonNull(response.body()).string()); 75 | } 76 | } catch (IOException e) { 77 | throw new RuntimeException(e); 78 | } 79 | } 80 | 81 | private String callBardToAsk(BardRequest bardRequest) { 82 | log.info("calling Bard with request {}", bardRequest); 83 | Call call = this.httpClient.newCall(createPostRequestForAsk(token, bardRequest)); 84 | 85 | try { 86 | try (Response response = call.execute()) { 87 | int statusCode = response.code(); 88 | log.info("Ask Response code: " + statusCode); 89 | 90 | if (statusCode != 200) { 91 | throw new IllegalStateException("Can't get the answer"); 92 | } 93 | 94 | String result = Objects.requireNonNull(response.body()).string().split("\\n")[3]; 95 | 96 | log.debug("Result for ask: {}", result); 97 | log.debug("Raw answers length: {}", result.length()); 98 | 99 | return result; 100 | } 101 | } catch (IOException e) { 102 | throw new RuntimeException(e); 103 | } 104 | } 105 | 106 | private Answer processAskResult(String content) { 107 | BardResponse bardResponse = renderBardResponseFromResponse(content); 108 | 109 | bardRequest.setConversationId(bardResponse.getConversationId()); 110 | bardRequest.setResponseId(bardResponse.getResponseId()); 111 | bardRequest.setChoiceId(bardResponse.getChoiceId()); 112 | 113 | return bardResponse.getAnswer(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Note: Archived as Google changes Bard to Gemini 3 | 4 | 5 | 6 | # Java Library for Google Bard to Ask Questions and Receive Answers 7 | 8 | `Google Bard` is Google's experimental, conversational, AI chat service. It is meant to function similarly to ChatGPT, with the biggest difference being that Google's service will pull its information from the web. 9 | 10 | I want to use `Google Bard` automatically in an easier way, so I built a [Java library](https://github.com/LarryDpk/Google-Bard) for it. The library supports continuous conversation with the same client. 11 | 12 | 13 | ## How to use the library 14 | ### Import the library into your project 15 | 16 | For maven project: 17 | ```xml 18 | 19 | 20 | com.pkslow 21 | google-bard 22 | 0.3.6 23 | 24 | 25 | ``` 26 | 27 | - 0.2.0+: Support images and it's not compatible with previous versions; 28 | - 0.3.4+: Support Chinese; 29 | - 0.3.5+: need two token: `__Secure-1PSID` and `__Secure-1PSIDTS` 30 | - 0.3.6: Support multiple lines by [Tolunay](https://github.com/TolunayM) 31 | 32 | ### Java Code 33 | It's easy to make the call: 34 | ```java 35 | AIClient client = new GoogleBardClient(token); 36 | Answer answer = client.ask("can you show me a picture of clock?"); 37 | ``` 38 | 39 | 40 | ### Get the token from browser 41 | We need to get the token from browser for authentication. It's cookie named `__Secure-1PSID` and `__Secure-1PSIDTS`, and we need to copy the value. 42 | Combine the two token as `$__Secure-1PSID;$__Secure-1PSIDTS` 43 | 44 | Example: 45 | ``` 46 | ZAiXYL4nedulA03ly0Ea2IdDTk2Emg4YJfuqs3YCcdxxxxxxxxx3XyDzlRqexw.;sidts-CjIBSAxbGXMW7bfOuuE0LOf-DDy20302Dh-npVoG**********86bhkxFwCw4QuaDyz1BAA 47 | ``` 48 | 49 | ![](https://pkslow.oss-cn-shenzhen.aliyuncs.com/images/2023/03/google-bard-python-chatbot.sessionid.png) 50 | 51 | ## SNlM0e is null 52 | If you hit SNlM0e is null issues, you may need to clear the cookie and login again: 53 | 54 | - Clear cookies of bard.google.com and again 55 | - login into the account 56 | - F12 > Applications > Cookies > bard > `__Secure-1PSID` and `__Secure-1PSIDTS` 57 | - Copy cookie and paste into your code. 58 | - Re run and you are good to go. 59 | 60 | ## The Example 61 | [example code to use](https://github.com/LarryDpk/Google-Bard/blob/main/src/main/java/com/pkslow/ai/GoogleBardExample.java) 62 | 63 | 64 | `Google Bard` is now under development so it may not be available for your country, so you may set the proxy before you run the application: 65 | ```java 66 | NetworkUtils.setUpProxy("localhost", "7890"); 67 | ``` 68 | 69 | 70 | It's `Markdown` format for the answer. 71 | --- 72 | ```markdown 73 | Sure thing. I found you a few photos of different types of clocks: 74 | 75 | * **Analog Clock:** This is the most common type of clock, and it has a face with hands that point to the hour, minute, and second. 76 | 77 | [![Image of Analog clock](https://cdn.shopify.com/s/files/1/0556/8066/3742/products/4550344275733_org_1200x1200.jpg?v=1678206891)](https://www.muji.us/products/analog-clock-l-laca0a) 78 | * **Digital Clock:** This type of clock displays the time in numbers, and it can be either battery-powered or plugged into an outlet. 79 | 80 | [![Image of Digital clock](https://m.media-amazon.com/images/I/61MuSYQ7yhL._AC_UF894,1000_QL80_.jpg)](https://www.amazon.in/YORTOT-Oversize-Control-Brightness-Temperature/dp/B08R8FW63J) 81 | * **Alarm Clock:** This type of clock is designed to wake you up at a certain time, and it can have a variety of features, such as snooze, a light, and a radio. 82 | 83 | [![Image of Alarm clock](https://m.media-amazon.com/images/I/71ggBUmny9L.jpg)](https://www.amazon.com/Sharp-Twin-Bell-Alarm-Clock/dp/B08TB22P29) 84 | * **Sundial:** This type of clock uses the sun to tell time, and it is a popular choice for people who want to live a more sustainable lifestyle. 85 | 86 | [![Image of Sundial](https://www.thehoarde.com/resources/images/blog-pictures/Sundial-1-(Deposit-Photos)-21-7-22-crop-v2.jpg)](https://www.thehoarde.com/blog/a-beginners-guide-to-the-garden-sundial) 87 | * **Cuckoo Clock:** This type of clock is a traditional European clock that has a cuckoo bird that pops out to announce the time. 88 | 89 | [![Image of Cuckoo clock](https://m.media-amazon.com/images/I/81OBtQVTkuL._AC_UF894,1000_QL80_.jpg)](https://www.amazon.com/Trenkle-Quartz-Cuckoo-Forest-Chopper/dp/B00VZQ5ZTY) 90 | 91 | I hope this helps! 92 | ``` 93 | 94 | ## Resources 95 | - [Amazing Bard Prompts](https://github.com/dsdanielpark/amazing-bard-prompts) 96 | - [Spring Boot Integration with Google Bard](https://www.pkslow.com/archives/spring-boot-google-bard) 97 | - [Python Lib: acheong08/Bard](https://github.com/acheong08/Bard) -------------------------------------------------------------------------------- /src/test/java/com/pkslow/ai/GoogleBardClientTest.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai; 2 | 3 | import com.google.common.io.Files; 4 | import com.pkslow.ai.domain.Answer; 5 | import com.pkslow.ai.domain.AnswerStatus; 6 | import okhttp3.Call; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | import org.junit.Assert; 11 | import org.junit.Test; 12 | import org.mockito.invocation.InvocationOnMock; 13 | 14 | import java.io.File; 15 | import java.io.IOException; 16 | import java.nio.charset.Charset; 17 | import java.time.Duration; 18 | 19 | import static com.pkslow.ai.util.WebUtils.okHttpClientWithTimeout; 20 | import static org.mockito.ArgumentMatchers.any; 21 | import static org.mockito.Mockito.*; 22 | 23 | public class GoogleBardClientTest { 24 | private static final String TOKEN = "xxx.xxx.token1;xxx.xxx.token2"; 25 | @Test 26 | public void constructor() { 27 | AIClient client = new GoogleBardClient("token"); 28 | Assert.assertNotNull(client); 29 | 30 | client = new GoogleBardClient("token", Duration.ofMinutes(10)); 31 | Assert.assertNotNull(client); 32 | 33 | OkHttpClient httpClient = okHttpClientWithTimeout(Duration.ofMinutes(10)); 34 | client = new GoogleBardClient("token", httpClient); 35 | Assert.assertNotNull(client); 36 | } 37 | 38 | @Test 39 | public void askNoImage() throws IOException { 40 | OkHttpClient httpClient = mock(OkHttpClient.class); 41 | AIClient client = new GoogleBardClient(TOKEN, httpClient); 42 | 43 | prepareMockForAsk("answer-response-body-no-image.json", httpClient); 44 | 45 | Answer answer = client.ask("What is the date today?"); 46 | verify(httpClient, times(2)).newCall(any(Request.class)); 47 | Assert.assertEquals(AnswerStatus.OK, answer.getStatus()); 48 | Assert.assertTrue(answer.getChosenAnswer().contains("As of today, June 28, 2023, it is Wednesday.")); 49 | } 50 | 51 | 52 | @Test 53 | public void askForImage() throws IOException { 54 | OkHttpClient httpClient = mock(OkHttpClient.class); 55 | AIClient client = new GoogleBardClient(TOKEN, httpClient); 56 | 57 | prepareMockForAsk("answer-response-body-with-image.json", httpClient); 58 | 59 | 60 | Answer answer = client.ask("can you show me a picture of Google?"); 61 | verify(httpClient, times(2)).newCall(any(Request.class)); 62 | Assert.assertEquals(AnswerStatus.OK, answer.getStatus()); 63 | Assert.assertTrue(answer.getChosenAnswer().contains("here is a picture of Google headquarters")); 64 | Assert.assertTrue(answer.markdown().contains("here is a picture of Google headquarters")); 65 | 66 | } 67 | 68 | @Test 69 | public void askForMultipleImages() throws IOException { 70 | OkHttpClient httpClient = mock(OkHttpClient.class); 71 | AIClient client = new GoogleBardClient(TOKEN, httpClient); 72 | 73 | prepareMockForAsk("answer-response-body-multiple-images.json", httpClient); 74 | 75 | Answer answer = client.ask("Show me some pictures of pumpkin"); 76 | verify(httpClient, times(2)).newCall(any(Request.class)); 77 | Assert.assertEquals(AnswerStatus.OK, answer.getStatus()); 78 | Assert.assertTrue(answer.getChosenAnswer().contains("here are some pictures of pumpkin")); 79 | Assert.assertTrue(answer.markdown().contains("here are some pictures of pumpkin")); 80 | 81 | } 82 | 83 | 84 | private void prepareMockForAsk(String answerBodyFile, OkHttpClient httpClient) throws IOException { 85 | ClassLoader classLoader = getClass().getClassLoader(); 86 | File sNlM0eFile = new File(classLoader.getResource("sNlM0e-response-body.txt").getFile()); 87 | File answerFile = new File(classLoader.getResource(answerBodyFile).getFile()); 88 | String sNlM0eBody = Files.toString(sNlM0eFile, Charset.defaultCharset()); 89 | String answerBody = Files.toString(answerFile, Charset.defaultCharset()); 90 | 91 | // sNlM0e part 92 | Call sNlM0eCall = mock(Call.class); 93 | Response sNlM0eResponse = mock(Response.class, RETURNS_DEEP_STUBS); 94 | when(sNlM0eCall.execute()).thenReturn(sNlM0eResponse); 95 | when(sNlM0eResponse.code()).thenReturn(200); 96 | when(sNlM0eResponse.body().string()).thenReturn(sNlM0eBody); 97 | 98 | // answer part 99 | Call answerCall = mock(Call.class); 100 | Response answerResponse = mock(Response.class, RETURNS_DEEP_STUBS); 101 | when(answerCall.execute()).thenReturn(answerResponse); 102 | when(answerResponse.code()).thenReturn(200); 103 | when(answerResponse.body().string()).thenReturn(answerBody); 104 | 105 | 106 | // mvn run test with keep return sNlM0eCall, no idea 107 | // when(httpClient.newCall(any(Request.class))).thenReturn(sNlM0eCall, answerCall); 108 | 109 | // https://stackoverflow.com/questions/8088179/using-mockito-with-multiple-calls-to-the-same-method-with-the-same-arguments 110 | when(httpClient.newCall(any(Request.class))).thenAnswer(new org.mockito.stubbing.Answer() { 111 | private int count = 0; 112 | 113 | public Call answer(InvocationOnMock invocation) { 114 | System.out.println("count: " + count); 115 | if (count++ == 0) { 116 | return sNlM0eCall; 117 | } else { 118 | return answerCall; 119 | } 120 | 121 | } 122 | }); 123 | 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/pkslow/ai/util/BardUtils.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.util; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonArray; 5 | import com.google.gson.JsonElement; 6 | import com.pkslow.ai.domain.*; 7 | import lombok.extern.slf4j.Slf4j; 8 | import okhttp3.FormBody; 9 | import okhttp3.HttpUrl; 10 | import okhttp3.Request; 11 | import okhttp3.RequestBody; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | import java.util.*; 15 | import java.util.concurrent.ThreadLocalRandom; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | 19 | import static com.pkslow.ai.util.Constants.*; 20 | 21 | @Slf4j 22 | public class BardUtils { 23 | 24 | public static Request.Builder createBuilderWithBardHeader(String token) { 25 | String[] tokens = token.split(";"); 26 | if (tokens.length < 2) { 27 | throw new RuntimeException("Please provide the correct token:" + TOKEN_COOKIE_1PSID + ";" + TOKEN_COOKIE_1PSIDTS); 28 | } 29 | String token1PSID = tokens[0]; 30 | String token1PSIDTS = tokens[1]; 31 | return new Request.Builder() 32 | .addHeader("Host", HOSTNAME) 33 | .addHeader("Content-Type", CONTENT_TYPE) 34 | .addHeader("X-Same-Domain", "1") 35 | .addHeader("User-Agent", USER_AGENT) 36 | .addHeader("Origin", BASE_URL) 37 | .addHeader("Referer", BASE_URL) 38 | .addHeader("Cookie", TOKEN_COOKIE_1PSID + "=" + token1PSID 39 | + ";" + TOKEN_COOKIE_1PSIDTS + 40 | "=" + token1PSIDTS); 41 | } 42 | 43 | public static Request createRequestForSNlM0e(String token) { 44 | Request.Builder headerBuilder = createBuilderWithBardHeader(token); 45 | return headerBuilder.url(BASE_URL) 46 | .build(); 47 | } 48 | 49 | public static String fetchSNlM0eFromBody(String input) { 50 | Matcher matcher = Pattern.compile("SNlM0e\":\"(.*?)\"").matcher(input); 51 | if (matcher.find()) { 52 | String result = matcher.group(); 53 | return result.substring(9, result.length() - 1); 54 | } 55 | return null; 56 | } 57 | 58 | @NotNull 59 | public static Map genQueryStringParamsForAsk() { 60 | int randomNumber = ThreadLocalRandom.current().nextInt(0, 10000) + 100000; 61 | 62 | Map params = new HashMap<>(); 63 | params.put("bl", BARD_VERSION); 64 | params.put("_reqid", String.valueOf(randomNumber)); 65 | params.put("rt", "c"); 66 | return params; 67 | } 68 | 69 | @NotNull 70 | public static HttpUrl.Builder createHttpBuilderForAsk() { 71 | HttpUrl.Builder httpBuilder = Objects 72 | .requireNonNull(HttpUrl.parse(BASE_URL + ASK_QUESTION_PATH)) 73 | .newBuilder(); 74 | 75 | for (Map.Entry param : genQueryStringParamsForAsk().entrySet()) { 76 | httpBuilder.addQueryParameter(param.getKey(), param.getValue()); 77 | } 78 | 79 | return httpBuilder; 80 | } 81 | 82 | /** 83 | * remove backslash \ in answer string 84 | */ 85 | public static String removeBackslash(String answerStr) { 86 | return answerStr 87 | .replace("\\\\n", "\n") 88 | .replace("\\", "\""); 89 | } 90 | 91 | @NotNull 92 | public static Request createPostRequestForAsk(String token, BardRequest bardRequest) { 93 | return createBuilderWithBardHeader(token) 94 | .url(createHttpBuilderForAsk().build()) 95 | .method("POST", buildRequestBodyForAsk(bardRequest)) 96 | .build(); 97 | } 98 | 99 | @NotNull 100 | public static RequestBody buildRequestBodyForAsk(BardRequest bardRequest) { 101 | String question = bardRequest.getQuestion().replace("\"", "\\\\\\\""); 102 | return new FormBody.Builder() 103 | .add("f.req", String.format("[null,\"[[\\\"%s\\\"],null,[\\\"%s\\\",\\\"%s\\\",\\\"%s\\\"]]\"]", 104 | question, bardRequest.getConversationId(), bardRequest.getResponseId(), bardRequest.getChoiceId())) 105 | .add("at", bardRequest.getStrSNlM0e()) 106 | .build(); 107 | } 108 | 109 | public static BardResponse renderBardResponseFromResponse(String content) { 110 | Answer.AnswerBuilder builder = Answer.builder(); 111 | String conversationId = ""; 112 | String responseId = ""; 113 | String choiceId = ""; 114 | 115 | try { 116 | JsonArray chatData = getChatData(content); 117 | 118 | builder.chosenAnswer(getChosenAnswer(chatData)); 119 | 120 | conversationId = ((JsonArray) chatData.get(1)).get(0).getAsString(); 121 | responseId = ((JsonArray) chatData.get(1)).get(1).getAsString(); 122 | choiceId = ((JsonArray) ((JsonArray) chatData.get(4)).get(0)).get(0).getAsString(); 123 | 124 | List images = new ArrayList<>(); 125 | 126 | try { 127 | images = getImages(chatData); 128 | } catch (Exception e) { 129 | log.info("No image"); 130 | } 131 | 132 | builder.images(images); 133 | 134 | return new BardResponse( 135 | conversationId, 136 | responseId, 137 | choiceId, 138 | builder.status(AnswerStatus.OK).build() 139 | ); 140 | 141 | } catch (Exception e) { 142 | return new BardResponse( 143 | conversationId, 144 | responseId, 145 | choiceId, 146 | builder.status(AnswerStatus.NO_ANSWER).build() 147 | ); 148 | } 149 | } 150 | 151 | public static boolean isEmpty(String str) { 152 | return str == null || str.length() == 0; 153 | } 154 | 155 | private static JsonArray getChatData(String content) { 156 | JsonArray contentJsonArray = new Gson().fromJson(content, JsonArray.class); 157 | String element3content = ((JsonArray) contentJsonArray.get(0)).get(2).getAsString(); 158 | return new Gson().fromJson(element3content, JsonArray.class); 159 | } 160 | 161 | private static String getChosenAnswer(JsonArray chatData) { 162 | return removeBackslash(((JsonArray) ((JsonArray) chatData.get(4)).get(0)).get(1).getAsString()); 163 | } 164 | 165 | private static List getImages(JsonArray chatData) { 166 | List images = new ArrayList<>(); 167 | 168 | JsonArray imagesJson = (JsonArray) (((JsonArray) ((JsonArray) chatData.get(4)).get(0)).get(4)); 169 | 170 | for (JsonElement jsonElement : imagesJson) { 171 | JsonArray imageJson = (JsonArray) jsonElement; 172 | 173 | String url = ((JsonArray) ((JsonArray) imageJson.get(0)).get(0)).get(0).getAsString(); 174 | String markdownLabel = imageJson.get(2).getAsString(); 175 | String articleURL = ((JsonArray) ((JsonArray) imageJson.get(1)).get(0)).get(0).getAsString(); 176 | 177 | Image image = new Image(url, markdownLabel, articleURL); 178 | images.add(image); 179 | } 180 | 181 | return images; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/test/java/com/pkslow/ai/util/BardUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.pkslow.ai.util; 2 | 3 | import com.pkslow.ai.domain.Answer; 4 | import com.pkslow.ai.domain.AnswerStatus; 5 | import com.pkslow.ai.domain.BardRequest; 6 | import com.pkslow.ai.domain.BardResponse; 7 | import okhttp3.HttpUrl; 8 | import okhttp3.Request; 9 | import org.junit.Assert; 10 | import org.junit.Test; 11 | 12 | import java.util.Map; 13 | 14 | import static com.pkslow.ai.util.Constants.BARD_VERSION; 15 | import static com.pkslow.ai.util.Constants.HOSTNAME; 16 | 17 | public class BardUtilsTest { 18 | private final String token = "xxx.xxx.token1;xxx.xxx.token2"; 19 | @Test 20 | public void createBuilderWithBardHeader() { 21 | Request.Builder builder = BardUtils.createBuilderWithBardHeader(token); 22 | Assert.assertNotNull(builder); 23 | } 24 | 25 | @Test 26 | public void createRequestForSNlM0e() { 27 | Request request = BardUtils.createRequestForSNlM0e(token); 28 | Assert.assertNotNull(request); 29 | Assert.assertEquals("GET", request.method()); 30 | Assert.assertEquals(HOSTNAME, request.header("HOST")); 31 | } 32 | 33 | @Test 34 | public void fetchSNlM0eFromBody() { 35 | String str = "\"LoQv7e\":false,\"Lz8rbb\":true,\"MT7f9b\":[],\"MuJWjd\":false,\"QrtxK\":\"0\",\"S06Grb\":\"111226985821558295512\",\"SNlM0e\":\"AFuTz6vZM6ljFX4ZoCj7nXmwSlrx:1684550912484\","; 36 | String result = BardUtils.fetchSNlM0eFromBody(str); 37 | Assert.assertEquals("AFuTz6vZM6ljFX4ZoCj7nXmwSlrx:1684550912484", result); 38 | } 39 | 40 | @Test 41 | public void genQueryStringParamsForAsk() { 42 | Map result = BardUtils.genQueryStringParamsForAsk(); 43 | Assert.assertEquals(BARD_VERSION, result.get("bl")); 44 | Assert.assertEquals("c", result.get("rt")); 45 | } 46 | 47 | @Test 48 | public void createHttpBuilderForAsk() { 49 | HttpUrl.Builder builder = BardUtils.createHttpBuilderForAsk(); 50 | Assert.assertNotNull(builder); 51 | } 52 | 53 | @Test 54 | public void removeBackslash() { 55 | String str = "It's www.pkslow.com\\\\n built by LarryDpk"; 56 | String result = BardUtils.removeBackslash(str); 57 | Assert.assertEquals("It's www.pkslow.com\n built by LarryDpk", result); 58 | } 59 | 60 | @Test 61 | public void createPostRequestForAsk() { 62 | BardRequest bardRequest = BardRequest.newEmptyBardRequest(); 63 | bardRequest.setStrSNlM0e("xxx1"); 64 | Request request = BardUtils.createPostRequestForAsk(token, bardRequest); 65 | Assert.assertNotNull(request); 66 | Assert.assertEquals("POST", request.method()); 67 | } 68 | 69 | @Test 70 | public void renderBardResponseFromResponse() { 71 | String content = "[[\"wrb.fr\",null,\"[[\\\"The weather in Hong Kong is currently 80°F and mostly cloudy. There is a 50% chance of rain showers. The humidity is 75%. The wind is blowing from the southeast at 5 to 10 mph.\\\\r\\\\n\\\\r\\\\nThe forecast for the rest of the day is for scattered showers and thunderstorms. The high temperature will be 84°F and the low temperature will be 79°F.\\\\r\\\\n\\\\r\\\\nHere is a more detailed forecast for the next few days:\\\\r\\\\n\\\\r\\\\n* Saturday, May 20: Scattered thunderstorms, especially during the afternoon hours. High temperature of 84°F and low temperature of 79°F.\\\\r\\\\n* Sunday, May 21: A t-storm around in the morning. High temperature of 89°F and low temperature of 78°F.\\\\r\\\\n* Monday, May 22: Mostly sunny. High temperature of 88°F and low temperature of 77°F.\\\\r\\\\n* Tuesday, May 23: A t-storm possible in the afternoon. High temperature of 87°F and low temperature of 76°F.\\\\r\\\\n* Wednesday, May 24: Mostly sunny. High temperature of 86°F and low temperature of 75°F.\\\\r\\\\n* Thursday, May 25: A t-storm possible in the afternoon. High temperature of 85°F and low temperature of 74°F.\\\\r\\\\n* Friday, May 26: Mostly sunny. High temperature of 84°F and low temperature of 73°F.\\\"],[\\\"c_16a1ebebd783b200\\\",\\\"r_16a1ebebd783bcab\\\"],[[\\\"weather Hong Kong\\\",1]],[],[[\\\"rc_16a1ebebd783bda3\\\",[\\\"The weather in Hong Kong is currently 80°F and mostly cloudy. There is a 50% chance of rain showers. The humidity is 75%. The wind is blowing from the southeast at 5 to 10 mph.\\\\r\\\\n\\\\r\\\\nThe forecast for the rest of the day is for scattered showers and thunderstorms. The high temperature will be 84°F and the low temperature will be 79°F.\\\\r\\\\n\\\\r\\\\nHere is a more detailed forecast for the next few days:\\\\r\\\\n\\\\r\\\\n* Saturday, May 20: Scattered thunderstorms, especially during the afternoon hours. High temperature of 84°F and low temperature of 79°F.\\\\r\\\\n* Sunday, May 21: A t-storm around in the morning. High temperature of 89°F and low temperature of 78°F.\\\\r\\\\n* Monday, May 22: Mostly sunny. High temperature of 88°F and low temperature of 77°F.\\\\r\\\\n* Tuesday, May 23: A t-storm possible in the afternoon. High temperature of 87°F and low temperature of 76°F.\\\\r\\\\n* Wednesday, May 24: Mostly sunny. High temperature of 86°F and low temperature of 75°F.\\\\r\\\\n* Thursday, May 25: A t-storm possible in the afternoon. High temperature of 85°F and low temperature of 74°F.\\\\r\\\\n* Friday, May 26: Mostly sunny. High temperature of 84°F and low temperature of 73°F.\\\"],[]],[\\\"rc_16a1ebebd783b184\\\",[\\\"The weather in Hong Kong is currently 80°F and mostly cloudy. There is a 50% chance of rain showers and thunderstorms. The humidity is 75%. The wind is blowing from the south-southeast at 5 to 10 miles per hour.\\\\r\\\\n\\\\r\\\\nThe forecast for the rest of the day is for mostly cloudy skies with a chance of rain showers and thunderstorms. The high temperature will be 84°F and the low temperature will be 79°F. The humidity will remain high, at around 75%. The wind will continue to blow from the south-southeast at 5 to 10 miles per hour.\\\\r\\\\n\\\\r\\\\nThe forecast for the next few days is for mostly cloudy skies with a chance of rain showers and thunderstorms. The high temperatures will be in the mid-80s and the low temperatures will be in the mid-70s. The humidity will remain high, at around 75%. The wind will continue to blow from the south-southeast at 5 to 10 miles per hour.\\\"],[]],[\\\"rc_16a1ebebd783b565\\\",[\\\"The weather in Hong Kong is currently 80°F and mostly cloudy. There is a 50% chance of rain showers. The humidity is 75%. The wind is blowing from the south-southeast at 5 to 10 mph.\\\\r\\\\n\\\\r\\\\nThe forecast for the next few days is as follows:\\\\r\\\\n\\\\r\\\\n* Saturday, May 20: A t-storm around in the morning, then mostly sunny in the afternoon. High near 84°F. Chance of precipitation is 40%.\\\\r\\\\n* Sunday, May 21: Sunny, with a high near 89°F.\\\\r\\\\n* Monday, May 22: Mostly sunny, with a high near 87°F.\\\\r\\\\n* Tuesday, May 23: Sunny, with a high near 86°F.\\\\r\\\\n* Wednesday, May 24: Mostly sunny, with a high near 85°F.\\\\r\\\\n* Thursday, May 25: Sunny, with a high near 84°F.\\\\r\\\\n* Friday, May 26: Mostly sunny, with a high near 83°F.\\\"],[]]]]\"]]"; 72 | BardResponse response = BardUtils.renderBardResponseFromResponse(content); 73 | Assert.assertNotNull(response); 74 | Assert.assertEquals("c_16a1ebebd783b200", response.getConversationId()); 75 | Assert.assertEquals("r_16a1ebebd783bcab", response.getResponseId()); 76 | Assert.assertEquals("rc_16a1ebebd783bda3", response.getChoiceId()); 77 | 78 | Answer answer = response.getAnswer(); 79 | Assert.assertNotNull(answer); 80 | Assert.assertEquals(AnswerStatus.OK, answer.getStatus()); 81 | Assert.assertTrue(answer.getChosenAnswer().contains("The weather in Hong Kong is currently 80°F and mostly cloudy.")); 82 | // Assert.assertEquals(3, answer.draftAnswers().size()); 83 | // Assert.assertEquals(answer.getChosenAnswer(), answer.getdraftAnswers().get(0)); 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.pkslow 8 | google-bard 9 | 0.3.6 10 | jar 11 | 12 | Pkslow google-bard 13 | A Java Lib for Google-Bard 14 | https://github.com/LarryDpk/Google-Bard 15 | 16 | 17 | 1.8 18 | 1.8 19 | UTF-8 20 | 4.10.0 21 | 2.10.1 22 | 1.3.6 23 | 1.18.26 24 | 4.13.2 25 | 0.7.6 26 | 4.11.0 27 | 31.1-jre 28 | 0.8.10 29 | false 30 | 31 | 32 | 33 | 34 | com.squareup.okhttp3 35 | okhttp 36 | ${okhttp.version} 37 | 38 | 39 | 40 | com.google.code.gson 41 | gson 42 | ${gson.version} 43 | 44 | 45 | ch.qos.logback 46 | logback-classic 47 | ${logback-classic.version} 48 | 49 | 50 | org.projectlombok 51 | lombok 52 | ${lombok.version} 53 | provided 54 | 55 | 56 | junit 57 | junit 58 | ${junit.version} 59 | test 60 | 61 | 62 | pl.pojo 63 | pojo-tester 64 | ${pl.pojo.version} 65 | test 66 | 67 | 68 | 69 | org.mockito 70 | mockito-inline 71 | ${mockito.version} 72 | test 73 | 74 | 75 | 76 | com.google.guava 77 | guava 78 | ${guava.version} 79 | test 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | MIT 88 | https://github.com/LarryDpk/Google-Bard/blob/main/LICENSE 89 | 90 | 91 | 92 | 93 | 94 | larrydpk 95 | larrydpk 96 | larry.dpk@gmail.com 97 | 98 | Java Developer 99 | 100 | +8 101 | 102 | 103 | 104 | 105 | https://github.com/LarryDpk/Google-Bard.git 106 | scm:git:ssh://git@github.com:LarryDpk/Google-Bard.git 107 | https://github.com/LarryDpk/Google-Bard 108 | 109 | 110 | 111 | 112 | ossrh 113 | 114 | true 115 | 116 | 117 | 118 | 119 | org.sonatype.plugins 120 | nexus-staging-maven-plugin 121 | 1.6.7 122 | true 123 | 124 | ossrh 125 | https://s01.oss.sonatype.org/ 126 | true 127 | 128 | 129 | 130 | 131 | org.apache.maven.plugins 132 | maven-source-plugin 133 | 2.2.1 134 | 135 | 136 | attach-sources 137 | 138 | jar-no-fork 139 | 140 | 141 | 142 | 143 | 144 | 145 | org.apache.maven.plugins 146 | maven-javadoc-plugin 147 | 2.9.1 148 | 149 | 150 | attach-javadocs 151 | 152 | jar 153 | 154 | 155 | 156 | 157 | 158 | 159 | org.apache.maven.plugins 160 | maven-gpg-plugin 161 | 1.5 162 | 163 | 164 | sign-artifacts 165 | install 166 | 167 | sign 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | ossrh 179 | https://s01.oss.sonatype.org/content/repositories/snapshots 180 | 181 | 182 | ossrh 183 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | org.jacoco 195 | jacoco-maven-plugin 196 | ${jacoco.version} 197 | 198 | ${maven.test.skip} 199 | ${basedir}/target/coverage-reports/jacoco-unit.exec 200 | ${basedir}/target/coverage-reports/jacoco-unit.exec 201 | file 202 | true 203 | 204 | com/pkslow/ai/AIClient.class 205 | com/pkslow/ai/GoogleBardExample.class 206 | com/pkslow/ai/util/Constants.class 207 | 208 | 209 | 210 | 211 | BUNDLE 212 |    213 | 214 | METHOD 215 | COVEREDRATIO 216 | 0.85 217 | 218 | 219 | LINE 220 | COVEREDRATIO 221 | 0.85 222 | 223 | 224 | CLASS 225 | MISSEDCOUNT 226 | 0 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | jacoco-initialize 236 | 237 | prepare-agent 238 | 239 | test-compile 240 | 241 | 242 | 243 | check 244 | 245 | check 246 | 247 | 248 | 249 | 250 | jacoco-site 251 | verify 252 | 253 | report 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------- /src/test/resources/answer-response-body-multiple-images.json: -------------------------------------------------------------------------------- 1 | )]}' 2 | 3 | 19708 4 | [["wrb.fr",null,"[[\"Sure, here are some pictures of pumpkin:\\n[Image of Pumpkin on white background]\\n[Image of Pumpkin patch]\\n[Image of Carved pumpkin]\\n[Image of Roasted pumpkin]\\n[Image of Pumpkin pie]\"],[\"c_297c1d8c61d08edf\",\"r_4277c915afa369b4\"],[[\"pumpkin picture\",1],[\"What is called pumpkin?\",4]],[],[[\"rc_4277c915afa36617\",[\"Sure, here are some pictures of pumpkin:\\n[Image of Pumpkin on white background]\\n[Image of Pumpkin patch]\\n[Image of Carved pumpkin]\\n[Image of Roasted pumpkin]\\n[Image of Pumpkin pie]\"],[],null,[[[[\"https://img.freepik.com/premium-photo/pumpkin-white-background_44074-2234.jpg?w\\u003d2000\"],null,2000,2000,\"Pumpkin on white background\",\"https://www.google.com/imgres?imgurl\\u003dhttps://img.freepik.com/premium-photo/pumpkin-white-background_44074-2234.jpg%3Fw%3D2000\\u0026imgrefurl\\u003dhttps://www.freepik.com/premium-photo/pumpkin-white-background_3880301.htm\\u0026tbnid\\u003dDcqhPV5499YEWM\\u0026docid\\u003dgRpOT3ubPSKI7M\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.freepik.com/premium-photo/pumpkin-white-background_3880301.htm\"],\"Freepik\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcR8vPEG2iTg3MGZmO9cJVoui-97TJ926Cn-zNMDN4a9dbH7YiE7SRucnvFDx8C1HS8RAQzVyagB5LtnjkpaM2mq38zysaMhDM3i\"],\"[Image of Pumpkin on white background]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_xHmQZmDa2cla4RJdwoFPU64FB36QbUrYtdmgrsSpQ4UQYO1eWd02HNlBtjN4igCH-a7zCiMuCnpCZppYuT4udzl0UP8fO7K4u2dftl9GPZZ5qcbfO_30h21vKZS3Yk4p2aUQ8m1vySGXiFXpiOGB0R6X188-FXpQ\\u003dw250-h200-p\"],null,225,225],0],[[[\"https://www.southernliving.com/thmb/uMtdjsRrccmL_KAQ9Lo7H9_UmLc\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/autumn-pumpkin-patch-SAFEFALL0920-aad6ce6ab01c45c2bd56a49acf648b83.jpg\"],null,1500,1000,\"Pumpkin patch\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.southernliving.com/thmb/uMtdjsRrccmL_KAQ9Lo7H9_UmLc%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/autumn-pumpkin-patch-SAFEFALL0920-aad6ce6ab01c45c2bd56a49acf648b83.jpg\\u0026imgrefurl\\u003dhttps://www.southernliving.com/travel/editors-best-pumpkin-patch\\u0026tbnid\\u003dyk8TgACLO_3juM\\u0026docid\\u003d94SiFOu_8sNN7M\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.southernliving.com/travel/editors-best-pumpkin-patch\"],\"Southern Living\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSup2de7-S-Y4XcWBECUFXh8ZUf6UZ0OcOdVFvBIvpyFmUn1W46vLQcceqMC74l-KhOGMPPFwqb_m7MLsXIt1EJUGTcIXpS_rXfC1ajcNrY_A\"],\"[Image of Pumpkin patch]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_xeaerHpjt3ljxr4NSqqQajvnLpKP5s-1n9WbtJ_XIUsas8i7R2Yec5hHY_5ZY0Y14T2eJnktbP3Cbylu3WR5hMFyNxf-RUROkPNu-Msou4-QBCFBT__C6o21oIDTQZ3kaiM8t3loJP86aT9Kv7NshmmDkb9xzC3aFNhihzD6pg3gAlblZNGQBANMnvXs0t5kVGSo-iodQk_jB1iX2OPuzHAS-uRtvbiFkeDTkvslpQ9dEM2-WinaWuTFn_Q9oPvbb5C0Ih5xumNU9hL8YbmDoiIIr8ivWAuYQ6mAwUH2cc9tlwR3oT\\u003dw250-h200-p\"],null,275,183],0],[[[\"https://www.treehugger.com/thmb/yoSfHs6jom8_sffc1K9f3TCdzOQ\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/how-preserve-carved-pumpkin-4868733-02-0bf73761175c43b99b96251e0acd16e9.jpg\"],null,1500,1001,\"Carved pumpkin\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.treehugger.com/thmb/yoSfHs6jom8_sffc1K9f3TCdzOQ%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/how-preserve-carved-pumpkin-4868733-02-0bf73761175c43b99b96251e0acd16e9.jpg\\u0026imgrefurl\\u003dhttps://www.treehugger.com/how-preserve-carved-pumpkin-4868733\\u0026tbnid\\u003dXsMUxC_sTo0qZM\\u0026docid\\u003dyge2zpvFXVa7WM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.treehugger.com/how-preserve-carved-pumpkin-4868733\"],\"Treehugger\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcRU3ebcLx79IC4IYf5r00EFW3Xtqdv4_sybiZnHgsTLBIizx-FxEX6pivwW6kV_xGtCbI7Dxv2OsA0mC7b2zcjy6THPWRGf6d-xRTdA\"],\"[Image of Carved pumpkin]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_zm0aG4e-9X6Yt2dDYo2pySsYUwXuSxoUaXiQwn-mOsN6jSddJ76NTkhxx5Y5a5iS0VM9TTKogug8PyerSmdt_E02krPJRS8eqDcK0EJAImWYuRG6K3CIYYM_CF_ZhTbi6wX6MFAWonVy3ZCEkkT9pQrm-CVxXlHJAYG8N9e1T_8qcfu78cgdJd1ZRtqvvR0s3verYX5eLG6-wLkzx6bzrpwrNn4y0rcnHG1kZe5erwaldxwC8UbJazoNqHsnMEAJ30ucIugtXbcvp_vEDc8n51KsLPo23KDIxbnLhTfULRu_ROfoX8\\u003dw250-h200-p\"],null,275,183],0],[[[\"https://img.taste.com.au/Hlg962yo/taste/2016/11/roasted-pumpkin-and-garlic-93890-1.jpeg\"],null,3000,2000,\"Roasted pumpkin\",\"https://www.google.com/imgres?imgurl\\u003dhttps://img.taste.com.au/Hlg962yo/taste/2016/11/roasted-pumpkin-and-garlic-93890-1.jpeg\\u0026imgrefurl\\u003dhttps://www.taste.com.au/recipes/roasted-pumpkin-garlic/34e219d9-4ee2-4011-bf80-99b9b8e83933\\u0026tbnid\\u003d7ZTbSMeoloxm-M\\u0026docid\\u003dsPy4m-Hcnal1EM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.taste.com.au/recipes/roasted-pumpkin-garlic/34e219d9-4ee2-4011-bf80-99b9b8e83933\"],\"Taste\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcRWIvK_PHCjLQqrAr7_abWZQnrjKvBGrGOzFyGIE4JzWlG1bIvPFsuYtnOdnuCcUkVwHHXKURZiIOnwBWM52nExa379wUy1Yvg8ZA\"],\"[Image of Roasted pumpkin]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_xoQrjtcVpGX_Jpq9ip1Jn_i934WWa9I0BZgxCTczmf8TzuxsMKAzxzdjBoUgS97oVcTFuKKBrOb4yLVCwdxY0MZO_xdiXSKQvsLm7sXmkvf0HnE0FN66RtnBw5qd8uFWenMxY5b8HzKEPUe9DMQbQkjNZp7vchSv3k\\u003dw250-h200-p\"],null,275,183],0],[[[\"https://www.allrecipes.com/thmb/9xC4E3ciEFc6xjLiA6rdEDLbInk\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/23439-PerfectPumpkinPie_002-4x3-1-44d015659c5c4a0888238d8f22de2a5e.jpg\"],null,1500,1125,\"Pumpkin pie\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.allrecipes.com/thmb/9xC4E3ciEFc6xjLiA6rdEDLbInk%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/23439-PerfectPumpkinPie_002-4x3-1-44d015659c5c4a0888238d8f22de2a5e.jpg\\u0026imgrefurl\\u003dhttps://www.allrecipes.com/recipe/23439/perfect-pumpkin-pie/\\u0026tbnid\\u003dwpkHn5TifksurM\\u0026docid\\u003dpmKo2tsl2Q8NkM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.allrecipes.com/recipe/23439/perfect-pumpkin-pie/\"],\"Allrecipes\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSLcFuOQ7EW2Vahfo5ubCD8rjqEOAk4lQLzs7fazvtC84Sm8SceXc6jl7hzo-ffPa9gLuDeLoXArIaKefJ0d6tv9Wvv9gXy11aiYW0Y\"],\"[Image of Pumpkin pie]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_zvtzIyALbvrlLBscdjjitMWiDTiqaDT4VW-kSeKqnKiiBp0A9xFFFCzpPU6obBET7SMWZayny5Grv9nGlUOo6i2PALaTtYhWSGxMUhF14dkBKWVUCOUSJBnPy4w8ZOkrNF2kTcQkvXRCjayQiLsSjZlIIAeVQRw7yy6rrv-K_HWp475UC3MIlfDnX3p8OKKWfUQjWXoyDA1SKV3_LPdRaQusqlgzYp9J1T1zlF7CHkzphPfpgad7CGwscKSHPF4GK2Lsjt65kQvR3fAG1H6L85SU35PL6PaUozXv5f8B59rkY\\u003dw250-h200-p\"],null,259,194],0]],null,true],[\"rc_4277c915afa361f6\",[\"Sure, I found you some pictures of pumpkin.\\n[Image of Whole pumpkin]\\n[Image of Sliced pumpkin]\\n[Image of Carved pumpkin]\\n[Image of Pumpkin soup]\\n[Image of Pumpkin pie]\"],[],null,[[[[\"https://tastyoven.com/wp-content/uploads/2021/09/instant-pot-whole-pumpkin-picture.jpg\"],null,1200,1200,\"Whole pumpkin\",\"https://www.google.com/imgres?imgurl\\u003dhttps://tastyoven.com/wp-content/uploads/2021/09/instant-pot-whole-pumpkin-picture.jpg\\u0026imgrefurl\\u003dhttps://tastyoven.com/instant-pot-pumpkin-how-to-cook-a-whole-pumpkin/\\u0026tbnid\\u003dFNus3keiMsbMYM\\u0026docid\\u003dlu3bnRrJEG9G1M\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://tastyoven.com/instant-pot-pumpkin-how-to-cook-a-whole-pumpkin/\"],\"Tasty Oven\",1,\"https://encrypted-tbn0.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSR5rTBkJ3rNhyQlO9KqVm49ZWPUTz5Egx5g1o5jvYFWEm1iD7pZ66D7BQA7nrJAL2GsUqi6oK7RskCs06wBZvC7mcJhOqIHQ\"],\"[Image of Whole pumpkin]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_xRVLb-b9HscP-ItjW0a1UrrxjbbfCtMnbjEAWvmux8QxXljgBZPU5KiH2pQdVCswvGSIBHeGxaHmZpxwiaSybKSJiK0Aih7mh8rJvVwbXbuzyq-ATpcRWPN82irm6_iObG-fsOh5yzgjLUoT5_halTCFdNhZsd7zRN\\u003dw250-h200-p\"],null,225,225],0],[[[\"https://en.pimg.jp/067/196/852/1/67196852.jpg\"],null,450,318,\"Sliced pumpkin\",\"https://www.google.com/imgres?imgurl\\u003dhttps://en.pimg.jp/067/196/852/1/67196852.jpg\\u0026imgrefurl\\u003dhttps://www.pixtastock.com/photo/67196852\\u0026tbnid\\u003d0pUe4AafjYFGaM\\u0026docid\\u003dCwoM_ZyX2nFAEM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.pixtastock.com/photo/67196852\"],\"PIXTA\",1,\"https://encrypted-tbn0.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcTJFcVBeHVQvUuS53IdYYGEQbWE0eY-Qhm0LqoCIu9Gm5deNW11pXq8G6wg7vKVWMKc0rsW0uz-zDB-kFPdHPcq7EceXz5_l97u5wf1\"],\"[Image of Sliced pumpkin]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_z_aisVRose0rApJzVsepjsZdRAIuFe61WZREsAKEOfKdiAwpwy2IS7YSDoksMdjcHQt9TBFZpkRjnxPx6x_2GojlcvawF5MCJ3jlV_lj-klQ\\u003dw250-h200-p\"],null,267,189],0],[[[\"https://www.treehugger.com/thmb/yoSfHs6jom8_sffc1K9f3TCdzOQ\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/how-preserve-carved-pumpkin-4868733-02-0bf73761175c43b99b96251e0acd16e9.jpg\"],null,1500,1001,\"Carved pumpkin\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.treehugger.com/thmb/yoSfHs6jom8_sffc1K9f3TCdzOQ%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/how-preserve-carved-pumpkin-4868733-02-0bf73761175c43b99b96251e0acd16e9.jpg\\u0026imgrefurl\\u003dhttps://www.treehugger.com/how-preserve-carved-pumpkin-4868733\\u0026tbnid\\u003dXsMUxC_sTo0qZM\\u0026docid\\u003dyge2zpvFXVa7WM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.treehugger.com/how-preserve-carved-pumpkin-4868733\"],\"Treehugger\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcRU3ebcLx79IC4IYf5r00EFW3Xtqdv4_sybiZnHgsTLBIizx-FxEX6pivwW6kV_xGtCbI7Dxv2OsA0mC7b2zcjy6THPWRGf6d-xRTdA\"],\"[Image of Carved pumpkin]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_zm0aG4e-9X6Yt2dDYo2pySsYUwXuSxoUaXiQwn-mOsN6jSddJ76NTkhxx5Y5a5iS0VM9TTKogug8PyerSmdt_E02krPJRS8eqDcK0EJAImWYuRG6K3CIYYM_CF_ZhTbi6wX6MFAWonVy3ZCEkkT9pQrm-CVxXlHJAYG8N9e1T_8qcfu78cgdJd1ZRtqvvR0s3verYX5eLG6-wLkzx6bzrpwrNn4y0rcnHG1kZe5erwaldxwC8UbJazoNqHsnMEAJ30ucIugtXbcvp_vEDc8n51KsLPo23KDIxbnLhTfULRu_ROfoX8\\u003dw250-h200-p\"],null,275,183],0],[[[\"https://www.allrecipes.com/thmb/My6kC-Dg-2mhIYNwQKP__-vN9iI\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/9191-PumpkinSoup-ddmfs-4X3-0150-0628bffddba64c2285d554ea97608f66.jpg\"],null,1500,1125,\"Pumpkin soup\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.allrecipes.com/thmb/My6kC-Dg-2mhIYNwQKP__-vN9iI%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/9191-PumpkinSoup-ddmfs-4X3-0150-0628bffddba64c2285d554ea97608f66.jpg\\u0026imgrefurl\\u003dhttps://www.allrecipes.com/recipe/9191/pumpkin-soup/\\u0026tbnid\\u003d1VC7ap2YqSBbgM\\u0026docid\\u003dBFkLE89ii21KRM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.allrecipes.com/recipe/9191/pumpkin-soup/\"],\"Allrecipes\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSLcFuOQ7EW2Vahfo5ubCD8rjqEOAk4lQLzs7fazvtC84Sm8SceXc6jl7hzo-ffPa9gLuDeLoXArIaKefJ0d6tv9Wvv9gXy11aiYW0Y\"],\"[Image of Pumpkin soup]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_w9yXSBrmDnh6Qk1e9mTKi2pVSyPEca0IRQM5LS0Ic51L5NARthODIhbMLgVCvfms5pEU1kT0nk7EhfLr0VcsDNzviy2a1R2IDAjC3eqiI-TRXp4ReW4s1dB2VNc-r4lb_n03sMpqhBGP8aZNL5xPcz6rvDBOyRFXFjocLtJJfQ2eXV5dWpWUYFP8U0gJ01TbWzgv5EdUhXbK1kSDFwf4oolQMabDotgCXxceJ4ypQd8IbmGPI-s6LEi8ZLSLZAtVq1QuXDU6_qK79cBxxPvNwKxzssa6Ac_YgcYV5uoseW\\u003dw250-h200-p\"],null,259,194],0],[[[\"https://www.allrecipes.com/thmb/9xC4E3ciEFc6xjLiA6rdEDLbInk\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/23439-PerfectPumpkinPie_002-4x3-1-44d015659c5c4a0888238d8f22de2a5e.jpg\"],null,1500,1125,\"Pumpkin pie\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.allrecipes.com/thmb/9xC4E3ciEFc6xjLiA6rdEDLbInk%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/23439-PerfectPumpkinPie_002-4x3-1-44d015659c5c4a0888238d8f22de2a5e.jpg\\u0026imgrefurl\\u003dhttps://www.allrecipes.com/recipe/23439/perfect-pumpkin-pie/\\u0026tbnid\\u003dwpkHn5TifksurM\\u0026docid\\u003dpmKo2tsl2Q8NkM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.allrecipes.com/recipe/23439/perfect-pumpkin-pie/\"],\"Allrecipes\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSLcFuOQ7EW2Vahfo5ubCD8rjqEOAk4lQLzs7fazvtC84Sm8SceXc6jl7hzo-ffPa9gLuDeLoXArIaKefJ0d6tv9Wvv9gXy11aiYW0Y\"],\"[Image of Pumpkin pie]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_zvtzIyALbvrlLBscdjjitMWiDTiqaDT4VW-kSeKqnKiiBp0A9xFFFCzpPU6obBET7SMWZayny5Grv9nGlUOo6i2PALaTtYhWSGxMUhF14dkBKWVUCOUSJBnPy4w8ZOkrNF2kTcQkvXRCjayQiLsSjZlIIAeVQRw7yy6rrv-K_HWp475UC3MIlfDnX3p8OKKWfUQjWXoyDA1SKV3_LPdRaQusqlgzYp9J1T1zlF7CHkzphPfpgad7CGwscKSHPF4GK2Lsjt65kQvR3fAG1H6L85SU35PL6PaUozXv5f8B59rkY\\u003dw250-h200-p\"],null,259,194],0]],null,true],[\"rc_4277c915afa36dd5\",[\"Sure, here are some pictures of pumpkin:\\n[Image of Pumpkin]\\n[Image of Carved pumpkin]\\n[Image of Pumpkin soup]\\n[Image of Pumpkin pie]\\n[Image of Pumpkin bread]\"],[],null,[[[[\"https://images.immediate.co.uk/production/volatile/sites/30/2020/02/pumpkin-3f3d894.jpg?quality\\u003d90\\u0026resize\\u003d556,505\"],null,556,505,\"Pumpkin\",\"https://www.google.com/imgres?imgurl\\u003dhttps://images.immediate.co.uk/production/volatile/sites/30/2020/02/pumpkin-3f3d894.jpg%3Fquality%3D90%26resize%3D556,505\\u0026imgrefurl\\u003dhttps://www.bbcgoodfood.com/glossary/pumpkin-glossary\\u0026tbnid\\u003dTAWcpwccbtC4bM\\u0026docid\\u003dN3kQVsppfUmRDM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.bbcgoodfood.com/glossary/pumpkin-glossary\"],\"BBC Good Food\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSExygKGd-mzDkwcUmAEYk7DsznBQ_BIWr-Tssmov4CIuT7eRfXMf6opGQYgNqXOVmQjFZFstNFOHB0jTCZ9UKFeGUwCpSqTkoFtOxhow\"],\"[Image of Pumpkin]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_xit9nslZYf-5xGfZupMU0HkQZP0UiqyENZskc1U32U8rog-FgcfA333BiSDLdYtTYsC7Xqu_MkgPUO-ATcjR1paOmoCzA--BW-E2zAqQ5YQvcSM5vgkKb1uwq0rwUXgIgzUQHnBGhPs3rb-NByA02kqaaekTQq08L9q1DucxcG1Ysxvh7XKhHrSSA6C2FsLL0NVOU\\u003dw250-h200-p\"],null,236,214],0],[[[\"https://www.treehugger.com/thmb/yoSfHs6jom8_sffc1K9f3TCdzOQ\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/how-preserve-carved-pumpkin-4868733-02-0bf73761175c43b99b96251e0acd16e9.jpg\"],null,1500,1001,\"Carved pumpkin\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.treehugger.com/thmb/yoSfHs6jom8_sffc1K9f3TCdzOQ%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/how-preserve-carved-pumpkin-4868733-02-0bf73761175c43b99b96251e0acd16e9.jpg\\u0026imgrefurl\\u003dhttps://www.treehugger.com/how-preserve-carved-pumpkin-4868733\\u0026tbnid\\u003dXsMUxC_sTo0qZM\\u0026docid\\u003dyge2zpvFXVa7WM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.treehugger.com/how-preserve-carved-pumpkin-4868733\"],\"Treehugger\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcRU3ebcLx79IC4IYf5r00EFW3Xtqdv4_sybiZnHgsTLBIizx-FxEX6pivwW6kV_xGtCbI7Dxv2OsA0mC7b2zcjy6THPWRGf6d-xRTdA\"],\"[Image of Carved pumpkin]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_zm0aG4e-9X6Yt2dDYo2pySsYUwXuSxoUaXiQwn-mOsN6jSddJ76NTkhxx5Y5a5iS0VM9TTKogug8PyerSmdt_E02krPJRS8eqDcK0EJAImWYuRG6K3CIYYM_CF_ZhTbi6wX6MFAWonVy3ZCEkkT9pQrm-CVxXlHJAYG8N9e1T_8qcfu78cgdJd1ZRtqvvR0s3verYX5eLG6-wLkzx6bzrpwrNn4y0rcnHG1kZe5erwaldxwC8UbJazoNqHsnMEAJ30ucIugtXbcvp_vEDc8n51KsLPo23KDIxbnLhTfULRu_ROfoX8\\u003dw250-h200-p\"],null,275,183],0],[[[\"https://www.allrecipes.com/thmb/My6kC-Dg-2mhIYNwQKP__-vN9iI\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/9191-PumpkinSoup-ddmfs-4X3-0150-0628bffddba64c2285d554ea97608f66.jpg\"],null,1500,1125,\"Pumpkin soup\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.allrecipes.com/thmb/My6kC-Dg-2mhIYNwQKP__-vN9iI%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/9191-PumpkinSoup-ddmfs-4X3-0150-0628bffddba64c2285d554ea97608f66.jpg\\u0026imgrefurl\\u003dhttps://www.allrecipes.com/recipe/9191/pumpkin-soup/\\u0026tbnid\\u003d1VC7ap2YqSBbgM\\u0026docid\\u003dBFkLE89ii21KRM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.allrecipes.com/recipe/9191/pumpkin-soup/\"],\"Allrecipes\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSLcFuOQ7EW2Vahfo5ubCD8rjqEOAk4lQLzs7fazvtC84Sm8SceXc6jl7hzo-ffPa9gLuDeLoXArIaKefJ0d6tv9Wvv9gXy11aiYW0Y\"],\"[Image of Pumpkin soup]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_w9yXSBrmDnh6Qk1e9mTKi2pVSyPEca0IRQM5LS0Ic51L5NARthODIhbMLgVCvfms5pEU1kT0nk7EhfLr0VcsDNzviy2a1R2IDAjC3eqiI-TRXp4ReW4s1dB2VNc-r4lb_n03sMpqhBGP8aZNL5xPcz6rvDBOyRFXFjocLtJJfQ2eXV5dWpWUYFP8U0gJ01TbWzgv5EdUhXbK1kSDFwf4oolQMabDotgCXxceJ4ypQd8IbmGPI-s6LEi8ZLSLZAtVq1QuXDU6_qK79cBxxPvNwKxzssa6Ac_YgcYV5uoseW\\u003dw250-h200-p\"],null,259,194],0],[[[\"https://www.allrecipes.com/thmb/9xC4E3ciEFc6xjLiA6rdEDLbInk\\u003d/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/23439-PerfectPumpkinPie_002-4x3-1-44d015659c5c4a0888238d8f22de2a5e.jpg\"],null,1500,1125,\"Pumpkin pie\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.allrecipes.com/thmb/9xC4E3ciEFc6xjLiA6rdEDLbInk%3D/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/23439-PerfectPumpkinPie_002-4x3-1-44d015659c5c4a0888238d8f22de2a5e.jpg\\u0026imgrefurl\\u003dhttps://www.allrecipes.com/recipe/23439/perfect-pumpkin-pie/\\u0026tbnid\\u003dwpkHn5TifksurM\\u0026docid\\u003dpmKo2tsl2Q8NkM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.allrecipes.com/recipe/23439/perfect-pumpkin-pie/\"],\"Allrecipes\",1,\"https://encrypted-tbn3.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcSLcFuOQ7EW2Vahfo5ubCD8rjqEOAk4lQLzs7fazvtC84Sm8SceXc6jl7hzo-ffPa9gLuDeLoXArIaKefJ0d6tv9Wvv9gXy11aiYW0Y\"],\"[Image of Pumpkin pie]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_zvtzIyALbvrlLBscdjjitMWiDTiqaDT4VW-kSeKqnKiiBp0A9xFFFCzpPU6obBET7SMWZayny5Grv9nGlUOo6i2PALaTtYhWSGxMUhF14dkBKWVUCOUSJBnPy4w8ZOkrNF2kTcQkvXRCjayQiLsSjZlIIAeVQRw7yy6rrv-K_HWp475UC3MIlfDnX3p8OKKWfUQjWXoyDA1SKV3_LPdRaQusqlgzYp9J1T1zlF7CHkzphPfpgad7CGwscKSHPF4GK2Lsjt65kQvR3fAG1H6L85SU35PL6PaUozXv5f8B59rkY\\u003dw250-h200-p\"],null,259,194],0],[[[\"https://www.onceuponachef.com/images/2009/09/Pumpkin-Bread-100.jpg\"],null,1000,817,\"Pumpkin bread\",\"https://www.google.com/imgres?imgurl\\u003dhttps://www.onceuponachef.com/images/2009/09/Pumpkin-Bread-100.jpg\\u0026imgrefurl\\u003dhttps://www.onceuponachef.com/recipes/spiced-pumpkin-bread.html\\u0026tbnid\\u003d3_obfIAyC_ZOQM\\u0026docid\\u003dyeMdPdDpm3OeRM\\u0026source\\u003dbard\\u0026hcb\\u003d1\"],[[\"https://www.onceuponachef.com/recipes/spiced-pumpkin-bread.html\"],\"Once Upon a Chef\",1,\"https://encrypted-tbn1.gstatic.com/favicon-tbn?q\\u003dtbn:ANd9GcQxmxLBwJgs8bvdHtq0l-ap_wWZjvGVJWiPNuN5o_4-sHZj5I_w6eMG2RSred8XAZGasHNE2mZbENFsm09DBw4e_wPYTE9GjFWgFQni7tri\"],\"[Image of Pumpkin bread]\",[[\"https://lh3.googleusercontent.com/bip/AKnpU_yPtUnfwPvm5XlF91rAP8U5iBguqSnBAj9LGxe2rARdsxPYV2ltZZZ38K7r8XaT_uNp5_6umkgKcXBy9fxgbPMDqco5rWxP47Nj-1p2R02rhabBUXF3-AZuRmQQadbDf0EnFtq_IQ\\u003dw250-h200-p\"],null,248,203],0]],null,true]],[\"Taipei City, Taiwan\",\"SWML_DESCRIPTION_FROM_YOUR_INTERNET_ADDRESS\",false,[[[null,null,null,[[300,200],14,null,[[238616205,1202726260],[262043067,1228582276]]]]],[[2,null,null,null,null,[null,null,null,[[[250329636,1215654268],146964.69,1931574222,1,864863983]]]]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[null,null,null,null,null,null,null,true]],\"//www.google.com/maps/vt/data\\u003dh3U2GRK4FxLyrWJxh7gphEQOzTZ_VRHA_s4KO0q3tVrpE12GBP86s9IilZHdlPJHRAqZp6NX2Q0DbIQYN8TCjKOUBhFvRcTQKBpTipz-fYgGlpGiixNFufjL1oYnTBH-4adR2x3UreZAMOjXf9UKPxIrezUu6bAs3xuSWO0d3ub3W6tWeM1olxcZNMtSgDl3\"]]"]] 5 | 58 6 | [["di",6883],["af.httprm",6883,"4281846178617013459",1]] 7 | 27 8 | [["e",4,null,null,19808]] 9 | --------------------------------------------------------------------------------