├── .gitignore ├── assets ├── img │ ├── favicon.ico │ ├── apple-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── ms-icon-70x70.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-196x196.png │ ├── android-icon-256x256.png │ ├── android-icon-512x512.png │ └── apple-icon-precomposed.png ├── css │ ├── style.css │ └── tailwind.min.css └── js │ ├── scripts.js │ └── alpine.min.js ├── go.mod ├── LICENSE ├── sw.js ├── go.sum ├── manifest.json ├── README.md ├── news └── news.go ├── main.go └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .env-* 3 | /tmp -------------------------------------------------------------------------------- /assets/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/favicon.ico -------------------------------------------------------------------------------- /assets/img/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon.png -------------------------------------------------------------------------------- /assets/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/favicon-16x16.png -------------------------------------------------------------------------------- /assets/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/favicon-32x32.png -------------------------------------------------------------------------------- /assets/img/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/favicon-96x96.png -------------------------------------------------------------------------------- /assets/img/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/ms-icon-70x70.png -------------------------------------------------------------------------------- /assets/img/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-57x57.png -------------------------------------------------------------------------------- /assets/img/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-60x60.png -------------------------------------------------------------------------------- /assets/img/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-72x72.png -------------------------------------------------------------------------------- /assets/img/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-76x76.png -------------------------------------------------------------------------------- /assets/img/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/ms-icon-144x144.png -------------------------------------------------------------------------------- /assets/img/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/ms-icon-150x150.png -------------------------------------------------------------------------------- /assets/img/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/ms-icon-310x310.png -------------------------------------------------------------------------------- /assets/img/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-36x36.png -------------------------------------------------------------------------------- /assets/img/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-48x48.png -------------------------------------------------------------------------------- /assets/img/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-72x72.png -------------------------------------------------------------------------------- /assets/img/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-96x96.png -------------------------------------------------------------------------------- /assets/img/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-114x114.png -------------------------------------------------------------------------------- /assets/img/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-120x120.png -------------------------------------------------------------------------------- /assets/img/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-144x144.png -------------------------------------------------------------------------------- /assets/img/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-152x152.png -------------------------------------------------------------------------------- /assets/img/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-180x180.png -------------------------------------------------------------------------------- /assets/img/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-144x144.png -------------------------------------------------------------------------------- /assets/img/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-192x192.png -------------------------------------------------------------------------------- /assets/img/android-icon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-196x196.png -------------------------------------------------------------------------------- /assets/img/android-icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-256x256.png -------------------------------------------------------------------------------- /assets/img/android-icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/android-icon-512x512.png -------------------------------------------------------------------------------- /assets/img/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahampriyanshu/gonewz/HEAD/assets/img/apple-icon-precomposed.png -------------------------------------------------------------------------------- /assets/css/style.css: -------------------------------------------------------------------------------- 1 | html,body{height:100%;-webkit-font-smoothing:antialiased;scrollbar-width:none;-ms-overflow-style:none}body::-webkit-scrollbar{display:none}::-moz-selection{color:white;background:#10b981}::selection{color:white;background:#10b981} -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ahampriyanshu/gonewz 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/howeyc/fsnotify v0.9.0 // indirect 7 | github.com/joho/godotenv v1.3.0 8 | github.com/mattn/go-colorable v0.1.8 // indirect 9 | github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a // indirect 10 | github.com/pilu/fresh v0.0.0-20190826141211-0fa698148017 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /assets/js/scripts.js: -------------------------------------------------------------------------------- 1 | var h=document.documentElement,b=document.body,st="scrollTop",sh="scrollHeight",progress=document.querySelector("#progress"),scroll;var scrollpos=window.scrollY;var header=document.getElementById("header");var navcontent=document.getElementById("nav-content");document.addEventListener("scroll",function(){scroll=(h[st]||b[st])/((h[sh]||b[sh])-h.clientHeight)*100;progress.style.setProperty("--scroll",scroll+"%");scrollpos=window.scrollY;if(scrollpos>10){header.classList.add("bg-white");header.classList.add("shadow-xl");navcontent.classList.remove("bg-gray-50");navcontent.classList.add("bg-white")}else{header.classList.remove("bg-white");header.classList.remove("shadow-xl");navcontent.classList.remove("bg-white");navcontent.classList.add("bg-gray-50")}}); 2 | if ('serviceWorker' in navigator) { 3 | navigator.serviceWorker 4 | .register('/sw.js') 5 | .then(function() { console.log('Service Worker Registered'); }); 6 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Priyanshu Tiwari 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 | -------------------------------------------------------------------------------- /sw.js: -------------------------------------------------------------------------------- 1 | const OFFLINE_VERSION = 1; 2 | const CACHE_NAME = 'offline'; 3 | const OFFLINE_URL = 'index.html'; 4 | 5 | self.addEventListener('install', (event) => { 6 | event.waitUntil((async () => { 7 | const cache = await caches.open(CACHE_NAME); 8 | await cache.add(new Request(OFFLINE_URL, {cache: 'reload'})); 9 | })()); 10 | }); 11 | 12 | self.addEventListener('activate', (event) => { 13 | event.waitUntil((async () => { 14 | if ('navigationPreload' in self.registration) { 15 | await self.registration.navigationPreload.enable(); 16 | } 17 | })()); 18 | self.clients.claim(); 19 | }); 20 | 21 | self.addEventListener('fetch', (event) => { 22 | if (event.request.mode === 'navigate') { 23 | event.respondWith((async () => { 24 | try { 25 | const preloadResponse = await event.preloadResponse; 26 | if (preloadResponse) { 27 | return preloadResponse; 28 | } 29 | const networkResponse = await fetch(event.request); 30 | return networkResponse; 31 | } catch (error) { 32 | console.log('Fetch failed; returning offline page instead.', error); 33 | const cache = await caches.open(CACHE_NAME); 34 | const cachedResponse = await cache.match(OFFLINE_URL); 35 | return cachedResponse; 36 | } 37 | })()); 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/howeyc/fsnotify v0.9.0 h1:0gtV5JmOKH4A8SsFxG2BczSeXWWPvcMT0euZt5gDAxY= 2 | github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1OzPjSJsA= 3 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 4 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 5 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 6 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 7 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 8 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 9 | github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a h1:Tg4E4cXPZSZyd3H1tJlYo6ZreXV0ZJvE/lorNqyw1AU= 10 | github.com/pilu/config v0.0.0-20131214182432-3eb99e6c0b9a/go.mod h1:9Or9aIl95Kp43zONcHd5tLZGKXb9iLx0pZjau0uJ5zg= 11 | github.com/pilu/fresh v0.0.0-20190826141211-0fa698148017 h1:XXDLZIIt9NqdeIEva0DM+z1npM0Tsx6h5TYqwNvXfP0= 12 | github.com/pilu/fresh v0.0.0-20190826141211-0fa698148017/go.mod h1:2LLTtftTZSdAPR/iVyennXZDLZOYzyDn+T0qEKJ8eSw= 13 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 14 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= 15 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 16 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Gonewz", 3 | "short_name": "Gonewz", 4 | "start_url": "/", 5 | "scope": "/", 6 | "display": "standalone", 7 | "background_color": "#F9FAFB", 8 | "theme_color": "#F9FAFB", 9 | "description": "Open Source news app in django and tailwind", 10 | "dir": "ltr", 11 | "lang": "en-US", 12 | "orientation": "portrait", 13 | "icons": [ 14 | { 15 | "src": "/assets/img/android-icon-36x36.png", 16 | "sizes": "36x36", 17 | "type": "image/png" 18 | }, 19 | { 20 | "src": "/assets/img/android-icon-48x48.png", 21 | "sizes": "48x48", 22 | "type": "image/png" 23 | }, 24 | { 25 | "src": "/assets/img/android-icon-72x72.png", 26 | "sizes": "72x72", 27 | "type": "image/png" 28 | }, 29 | { 30 | "src": "/assets/img/android-icon-96x96.png", 31 | "sizes": "96x96", 32 | "type": "image/png" 33 | }, 34 | { 35 | "src": "/assets/img/android-icon-144x144.png", 36 | "sizes": "144x144", 37 | "type": "image/png" 38 | }, 39 | { 40 | "src": "/assets/img/android-icon-192x192.png", 41 | "sizes": "192x192", 42 | "type": "image/png" 43 | }, 44 | { 45 | "src": "/assets/img/android-icon-256x256.png", 46 | "sizes": "256x256", 47 | "type": "image/png" 48 | }, 49 | { 50 | "src": "/assets/img/android-icon-512x512.png", 51 | "sizes": "512x512", 52 | "type": "image/png" 53 | }, 54 | { 55 | "src": "/assets/img/android-icon-196x196.png", 56 | "sizes": "196x196", 57 | "type": "image/png", 58 | "purpose": "maskable" 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gonewz 2 | 3 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://gonewz.herokuapp.com/) 4 | [![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://gonewz.herokuapp.com/) 5 | [![Open Source Love svg2](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://gonewz.herokuapp.com/) 6 | [![size](https://img.shields.io/github/repo-size/ahampriyanshu/gonewz?style=flat-square)](https://gonewz.herokuapp.com/) 7 | [![Website status](https://img.shields.io/website-up-down-green-red/http/shields.io.svg)](https://gonewz.herokuapp.com/) 8 | 9 | ## Home 10 | ![home](https://user-images.githubusercontent.com/54521023/103106650-39c44900-465d-11eb-873f-bcc2853a1ecf.png) 11 | 12 | ## Footer 13 | ![footer](https://user-images.githubusercontent.com/54521023/103106648-3761ef00-465d-11eb-82c0-61bcbe3c4417.png) 14 | 15 | ## Search 16 | ![search](https://user-images.githubusercontent.com/54521023/103106649-37fa8580-465d-11eb-9f5a-be244b760535.png) 17 | 18 | ## Mobile View 19 |

20 | 21 | 22 |

23 | 24 | ## Lighthouse Audit 25 |

26 | 27 |

28 | 29 | 30 | ## Setup 31 | 32 | ```bash 33 | 34 | git clone https://github.com/ahampriyanshu/gonewz.git && cd gonewz 35 | echo PORT=3000$'\n'NEWS_API_KEY="secret_key" >> .env 36 | go build && ./gonewz 37 | 38 | ``` 39 | 40 | * Change "secret_key" with your news_api_key. 41 | 42 | * For deployment on heroku, click [here](https://devcenter.heroku.com/articles/getting-started-with-go) 43 | 44 | ## Dependencies 45 | 46 | | Dependency | Version | 47 | | --- | --- | 48 | | Go | 1.15 | 49 | | Tailwind | 2.0 | 50 | | NewsAPI | 2.0 | 51 | 52 | * Special thanks to [Saurav](https://github.com/SauravKanchan) for providing [this](https://github.com/SauravKanchan/NewsAPI) wonderfull form of the newsapi. 53 | -------------------------------------------------------------------------------- /news/news.go: -------------------------------------------------------------------------------- 1 | package news 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "net/url" 9 | "time" 10 | ) 11 | 12 | /*Article : Structure to store the json object*/ 13 | type Article struct { 14 | Source struct { 15 | ID interface{} `json:"id"` 16 | Name string `json:"name"` 17 | } `json:"source"` 18 | Author string `json:"author"` 19 | Title string `json:"title"` 20 | Description string `json:"description"` 21 | URL string `json:"url"` 22 | URLToImage string `json:"urlToImage"` 23 | PublishedAt time.Time `json:"publishedAt"` 24 | } 25 | 26 | /*FormatPublishedDate : Formatting published date*/ 27 | func (a *Article) FormatPublishedDate() string { 28 | year, month, day := a.PublishedAt.Date() 29 | return fmt.Sprintf("%v %d, %d", month, day, year) 30 | } 31 | 32 | /*Results : Structure to store the results */ 33 | type Results struct { 34 | Status string `json:"status"` 35 | TotalResults int `json:"totalResults"` 36 | Articles []Article `json:"articles"` 37 | } 38 | 39 | /*Client : Structure to store http client */ 40 | type Client struct { 41 | http *http.Client 42 | key string 43 | PageSize int 44 | } 45 | 46 | /*FetchHeadline : To fetch the headlines*/ 47 | func (c *Client) FetchHeadline(page string) (*Results, error) { 48 | endpoint := fmt.Sprintf("https://saurav.tech/NewsAPI/top-headlines/category/general/in.json") 49 | resp, err := c.http.Get(endpoint) 50 | if err != nil { 51 | return nil, err 52 | } 53 | 54 | defer resp.Body.Close() 55 | 56 | body, err := ioutil.ReadAll(resp.Body) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | if resp.StatusCode != http.StatusOK { 62 | return nil, fmt.Errorf(string(body)) 63 | } 64 | 65 | res := &Results{} 66 | return res, json.Unmarshal(body, res) 67 | } 68 | 69 | /*FetchByCategory : Fectch for Category */ 70 | func (c *Client) FetchByCategory(category, page string) (*Results, error) { 71 | endpoint := fmt.Sprintf("https://saurav.tech/NewsAPI/top-headlines/category/%s/in.json", url.QueryEscape(category)) 72 | resp, err := c.http.Get(endpoint) 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | defer resp.Body.Close() 78 | 79 | body, err := ioutil.ReadAll(resp.Body) 80 | if err != nil { 81 | return nil, err 82 | } 83 | 84 | if resp.StatusCode != http.StatusOK { 85 | return nil, fmt.Errorf(string(body)) 86 | } 87 | 88 | res := &Results{} 89 | return res, json.Unmarshal(body, res) 90 | } 91 | 92 | /*FetchBySearch : To fetch the queries*/ 93 | func (c *Client) FetchBySearch(query, page string) (*Results, error) { 94 | endpoint := fmt.Sprintf("https://newsapi.org/v2/everything?q=%s&pageSize=%d&page=%s&apiKey=%s&sortBy=publishedAt&language=en", url.QueryEscape(query), c.PageSize, page, c.key) 95 | resp, err := c.http.Get(endpoint) 96 | if err != nil { 97 | return nil, err 98 | } 99 | 100 | defer resp.Body.Close() 101 | 102 | body, err := ioutil.ReadAll(resp.Body) 103 | if err != nil { 104 | return nil, err 105 | } 106 | 107 | if resp.StatusCode != http.StatusOK { 108 | return nil, fmt.Errorf(string(body)) 109 | } 110 | 111 | res := &Results{} 112 | return res, json.Unmarshal(body, res) 113 | } 114 | 115 | /*FetchBySource : To fetch by source*/ 116 | func (c *Client) FetchBySource(query, page string) (*Results, error) { 117 | endpoint := fmt.Sprintf("https://saurav.tech/NewsAPI/everything/%s.json", url.QueryEscape(query)) 118 | resp, err := c.http.Get(endpoint) 119 | if err != nil { 120 | return nil, err 121 | } 122 | 123 | defer resp.Body.Close() 124 | 125 | body, err := ioutil.ReadAll(resp.Body) 126 | if err != nil { 127 | return nil, err 128 | } 129 | 130 | if resp.StatusCode != http.StatusOK { 131 | return nil, fmt.Errorf(string(body)) 132 | } 133 | 134 | res := &Results{} 135 | return res, json.Unmarshal(body, res) 136 | } 137 | 138 | /*NewClient : 100 { 141 | pageSize = 100 142 | } 143 | 144 | return &Client{httpClient, key, pageSize} 145 | } 146 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "html/template" 6 | "io/ioutil" 7 | "log" 8 | "math" 9 | "net/http" 10 | "net/url" 11 | "os" 12 | "strconv" 13 | "time" 14 | 15 | "github.com/ahampriyanshu/gonewz/news" 16 | "github.com/joho/godotenv" 17 | ) 18 | 19 | var tpl = template.Must(template.ParseFiles("index.html")) 20 | 21 | /*Q structure of Q */ 22 | type Q struct { 23 | Query string 24 | NextPage int 25 | TotalPages int 26 | Results *news.Results 27 | Type int 28 | } 29 | 30 | /*IsLastPage : checking if the current page is the last page */ 31 | func (s *Q) IsLastPage() bool { 32 | return s.NextPage >= s.TotalPages 33 | } 34 | 35 | /*CurrentPage : fetching current page */ 36 | func (s *Q) CurrentPage() int { 37 | if s.NextPage == 1 { 38 | return s.NextPage 39 | } 40 | 41 | return s.NextPage - 1 42 | } 43 | 44 | /*PreviousPage : fetching previous page */ 45 | func (s *Q) PreviousPage() int { 46 | return s.CurrentPage() - 1 47 | } 48 | 49 | func dataHandler(newsapi *news.Client, pageType int) http.HandlerFunc { 50 | return func(w http.ResponseWriter, r *http.Request) { 51 | u, err := url.Parse(r.URL.String()) 52 | if err != nil { 53 | http.Error(w, err.Error(), http.StatusInternalServerError) 54 | return 55 | } 56 | 57 | params := u.Query() 58 | 59 | Query := params.Get("q") 60 | if Query == "" { 61 | Query = "Why am I so lonely" 62 | } 63 | page := params.Get("page") 64 | if page == "" { 65 | page = "1" 66 | } 67 | 68 | var results *news.Results 69 | 70 | switch pageType { 71 | case 1: 72 | results, err = newsapi.FetchHeadline(page) 73 | if err != nil { 74 | http.Error(w, err.Error(), http.StatusInternalServerError) 75 | return 76 | } 77 | case 2: 78 | results, err = newsapi.FetchBySearch(Query, page) 79 | if err != nil { 80 | http.Error(w, err.Error(), http.StatusInternalServerError) 81 | return 82 | } 83 | case 3: 84 | results, err = newsapi.FetchByCategory(Query, page) 85 | if err != nil { 86 | http.Error(w, err.Error(), http.StatusInternalServerError) 87 | return 88 | } 89 | case 4: 90 | results, err = newsapi.FetchBySource(Query, page) 91 | if err != nil { 92 | http.Error(w, err.Error(), http.StatusInternalServerError) 93 | return 94 | } 95 | default: 96 | results, err = newsapi.FetchBySearch(Query, page) 97 | if err != nil { 98 | http.Error(w, err.Error(), http.StatusInternalServerError) 99 | return 100 | } 101 | } 102 | 103 | nextPage, err := strconv.Atoi(page) 104 | if err != nil { 105 | http.Error(w, err.Error(), http.StatusInternalServerError) 106 | return 107 | } 108 | 109 | q := &Q{ 110 | Query: Query, 111 | NextPage: nextPage, 112 | TotalPages: int(math.Ceil(float64(results.TotalResults / newsapi.PageSize))), 113 | Results: results, 114 | Type: pageType, 115 | } 116 | 117 | if ok := !q.IsLastPage(); ok { 118 | q.NextPage++ 119 | } 120 | 121 | buf := &bytes.Buffer{} 122 | err = tpl.Execute(buf, q) 123 | if err != nil { 124 | http.Error(w, err.Error(), http.StatusInternalServerError) 125 | return 126 | } 127 | 128 | buf.WriteTo(w) 129 | } 130 | } 131 | 132 | func sendSW(w http.ResponseWriter, r *http.Request) { 133 | data, err := ioutil.ReadFile("sw.js") 134 | if err != nil { 135 | http.Error(w, "Couldn't read file", http.StatusInternalServerError) 136 | return 137 | } 138 | w.Header().Set("Content-Type", "application/javascript; charset=utf-8") 139 | w.Write(data) 140 | } 141 | 142 | func sendManifest(w http.ResponseWriter, r *http.Request) { 143 | data, err := ioutil.ReadFile("manifest.json") 144 | if err != nil { 145 | http.Error(w, "Couldn't read file", http.StatusInternalServerError) 146 | return 147 | } 148 | w.Header().Set("Content-Type", "application/json; charset=utf-8") 149 | w.Write(data) 150 | } 151 | 152 | func main() { 153 | err := godotenv.Load() 154 | if err != nil { 155 | log.Println("Error loading .env file") 156 | } 157 | 158 | port := os.Getenv("PORT") 159 | if port == "" { 160 | port = "3000" 161 | } 162 | 163 | apiKey := os.Getenv("NEWS_API_KEY") 164 | if apiKey == "" { 165 | log.Fatal("Env: apiKey must be set") 166 | } 167 | 168 | myClient := &http.Client{Timeout: 10 * time.Second} 169 | newsapi := news.NewClient(myClient, apiKey, 20) 170 | 171 | fs := http.FileServer(http.Dir("assets")) 172 | 173 | mux := http.NewServeMux() 174 | mux.Handle("/assets/", http.StripPrefix("/assets/", fs)) 175 | mux.HandleFunc("/sw.js", sendSW) 176 | mux.HandleFunc("/manifest.json", sendManifest) 177 | mux.HandleFunc("/", dataHandler(newsapi, 1)) 178 | mux.HandleFunc("/search", dataHandler(newsapi, 2)) 179 | mux.HandleFunc("/category", dataHandler(newsapi, 3)) 180 | mux.HandleFunc("/source", dataHandler(newsapi, 4)) 181 | http.ListenAndServe(":"+port, mux) 182 | } 183 | -------------------------------------------------------------------------------- /assets/css/tailwind.min.css: -------------------------------------------------------------------------------- 1 | /* modern-normalize v1.0.0 | MIT License | https://github.com/sindresorhus/modern-normalize */*,*::before,*::after{box-sizing:border-box}:root{-moz-tab-size:4;-o-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}body{font-family:system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji'}hr{height:0;color:inherit}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,'Liberation Mono',Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}button,[type='button'],[type='submit']{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}[type='search']{-webkit-appearance:textfield;outline-offset:-2px}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}button{background-color:transparent;background-image:none}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}fieldset{margin:0;padding:0}ol,ul{list-style:none;margin:0;padding:0}html{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";line-height:1.5}body{font-family:inherit;line-height:inherit}*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#9ca3af}input::placeholder,textarea::placeholder{color:#9ca3af}button,[role="button"]{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}pre,code,kbd,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.bg-black{--tw-bg-opacity:1;background-color:rgba(0,0,0,var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgba(249,250,251,var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgba(243,244,246,var(--tw-bg-opacity))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgba(55,65,81,var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgba(31,41,55,var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgba(239,68,68,var(--tw-bg-opacity))}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgba(245,158,11,var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgba(16,185,129,var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgba(5,150,105,var(--tw-bg-opacity))}.hover\:bg-gray-300:hover{--tw-bg-opacity:1;background-color:rgba(209,213,219,var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgba(5,150,105,var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;background-color:rgba(4,120,87,var(--tw-bg-opacity))}.bg-center{background-position:center}.bg-cover{background-size:cover}.border-transparent{border-color:transparent}.border-black{--tw-border-opacity:1;border-color:rgba(0,0,0,var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgba(243,244,246,var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgba(156,163,175,var(--tw-border-opacity))}.border-gray-500{--tw-border-opacity:1;border-color:rgba(107,114,128,var(--tw-border-opacity))}.border-red-900{--tw-border-opacity:1;border-color:rgba(127,29,29,var(--tw-border-opacity))}.border-yellow-900{--tw-border-opacity:1;border-color:rgba(120,53,15,var(--tw-border-opacity))}.border-green-400{--tw-border-opacity:1;border-color:rgba(52,211,153,var(--tw-border-opacity))}.border-green-900{--tw-border-opacity:1;border-color:rgba(6,78,59,var(--tw-border-opacity))}.rounded-none{border-radius:0}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-full{border-radius:9999px}.rounded-b-none{border-bottom-right-radius:0;border-bottom-left-radius:0}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-b-lg{border-bottom-right-radius:.5rem;border-bottom-left-radius:.5rem}.rounded-tr-lg{border-top-right-radius:.5rem}.rounded-br-lg{border-bottom-right-radius:.5rem}.border-none{border-style:none}.border{border-width:1px}.border-b-2{border-bottom-width:2px}.border-t{border-top-width:1px}.border-b{border-bottom-width:1px}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.cursor-not-allowed{cursor:not-allowed}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.hidden{display:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.content-center{align-content:center}.justify-start{justify-content:flex-start}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.flex-1{flex:1 1 0%}.flex-none{flex:none}.flex-grow{flex-grow:1}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}.font-light{font-weight:300}.font-normal{font-weight:400}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.h-1{height:.25rem}.h-3{height:.75rem}.h-4{height:1rem}.h-6{height:1.5rem}.h-8{height:2rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-16{height:4rem}.h-32{height:8rem}.h-48{height:12rem}.h-64{height:16rem}.h-auto{height:auto}.h-1\/2{height:50%}.h-full{height:100%}.h-screen{height:100vh}.text-xs{font-size:.75rem;line-height:1rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-5xl{font-size:3rem;line-height:1}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-none{line-height:1}.leading-normal{line-height:1.5}.leading-relaxed{line-height:1.625}.list-none{list-style-type:none}.my-1{margin-top:.25rem;margin-bottom:.25rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.mx-3{margin-left:.75rem;margin-right:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.my-6{margin-top:1.5rem;margin-bottom:1.5rem}.mx-6{margin-left:1.5rem;margin-right:1.5rem}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.my-auto{margin-top:auto;margin-bottom:auto}.mx-auto{margin-left:auto;margin-right:auto}.mt-0{margin-top:0}.mr-1{margin-right:.25rem}.mb-1{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.mb-2{margin-bottom:.5rem}.ml-2{margin-left:.5rem}.mt-3{margin-top:.75rem}.mr-3{margin-right:.75rem}.mb-3{margin-bottom:.75rem}.mt-4{margin-top:1rem}.mr-4{margin-right:1rem}.mb-4{margin-bottom:1rem}.mt-5{margin-top:1.25rem}.mb-5{margin-bottom:1.25rem}.ml-5{margin-left:1.25rem}.mt-6{margin-top:1.5rem}.mb-6{margin-bottom:1.5rem}.ml-6{margin-left:1.5rem}.mt-8{margin-top:2rem}.mb-8{margin-bottom:2rem}.mt-10{margin-top:2.5rem}.mb-10{margin-bottom:2.5rem}.mt-12{margin-top:3rem}.mb-20{margin-bottom:5rem}.mt-24{margin-top:6rem}.mt-32{margin-top:8rem}.mr-auto{margin-right:auto}.ml-auto{margin-left:auto}.-mr-1{margin-right:-0.25rem}.-mt-8{margin-top:-2rem}.-mt-16{margin-top:-4rem}.-mt-24{margin-top:-6rem}.max-w-md{max-width:28rem}.max-w-lg{max-width:32rem}.max-w-xl{max-width:36rem}.max-w-4xl{max-width:56rem}.max-w-full{max-width:100%}.max-w-screen-xl{max-width:1280px}.min-w-0{min-width:0}.object-cover{-o-object-fit:cover;object-fit:cover}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.hover\:opacity-75:hover{opacity:.75}.outline-none{outline:2px solid transparent;outline-offset:2px}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.overflow-hidden{overflow:hidden}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.py-0{padding-top:0;padding-bottom:0}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.px-12{padding-left:3rem;padding-right:3rem}.py-20{padding-top:5rem;padding-bottom:5rem}.pr-0{padding-right:0}.pt-1{padding-top:.25rem}.pb-1{padding-bottom:.25rem}.pl-1{padding-left:.25rem}.pt-2{padding-top:.5rem}.pb-2{padding-bottom:.5rem}.pt-3{padding-top:.75rem}.pb-3{padding-bottom:.75rem}.pt-4{padding-top:1rem}.pr-4{padding-right:1rem}.pb-4{padding-bottom:1rem}.pt-5{padding-top:1.25rem}.pt-6{padding-top:1.5rem}.pb-6{padding-bottom:1.5rem}.pt-8{padding-top:2rem}.pb-12{padding-bottom:3rem}.pr-16{padding-right:4rem}.pt-20{padding-top:5rem}.pt-32{padding-top:8rem}.pb-40{padding-bottom:10rem}.pb-64{padding-bottom:16rem}.placeholder-green-600::-moz-placeholder{--tw-placeholder-opacity:1;color:rgba(5,150,105,var(--tw-placeholder-opacity))}.placeholder-green-600:-ms-input-placeholder{--tw-placeholder-opacity:1;color:rgba(5,150,105,var(--tw-placeholder-opacity))}.placeholder-green-600::placeholder{--tw-placeholder-opacity:1;color:rgba(5,150,105,var(--tw-placeholder-opacity))}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.top-0{top:0}.right-0{right:0}*{--tw-shadow:0 0 #0000}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,0.05);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,0.1),0 1px 2px 0 rgba(0,0,0,0.06);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,0.1),0 2px 4px -1px rgba(0,0,0,0.06);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -2px rgba(0,0,0,0.05);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,0.1),0 10px 10px -5px rgba(0,0,0,0.04);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,0.25);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,0.06);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:shadow-lg:hover{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -2px rgba(0,0,0,0.05);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.focus\:shadow-none:focus{--tw-shadow:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}*{--tw-ring-inset:var(--tw-empty,/**//**/);--tw-ring-offset-width:0;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000}.fill-current{fill:currentColor}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-black{--tw-text-opacity:1;color:rgba(0,0,0,var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgba(255,255,255,var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgba(107,114,128,var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgba(55,65,81,var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgba(31,41,55,var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgba(17,24,39,var(--tw-text-opacity))}.text-green-500{--tw-text-opacity:1;color:rgba(16,185,129,var(--tw-text-opacity))}.text-green-600{--tw-text-opacity:1;color:rgba(5,150,105,var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity:1;color:rgba(79,70,229,var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-700{--tw-text-opacity:1;color:rgba(55,65,81,var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgba(75,85,99,var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgba(17,24,39,var(--tw-text-opacity))}.hover\:text-green-500:hover{--tw-text-opacity:1;color:rgba(16,185,129,var(--tw-text-opacity))}.hover\:text-green-600:hover{--tw-text-opacity:1;color:rgba(5,150,105,var(--tw-text-opacity))}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.uppercase{text-transform:uppercase}.no-underline{text-decoration:none}.hover\:underline:hover{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.tracking-normal{letter-spacing:0}.align-middle{vertical-align:middle}.break-normal{overflow-wrap:normal;word-break:normal}.break-words{overflow-wrap:break-word}.w-3{width:.75rem}.w-4{width:1rem}.w-6{width:1.5rem}.w-8{width:2rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-16{width:4rem}.w-48{width:12rem}.w-4\/5{width:80%}.w-full{width:100%}.w-screen{width:100vw}.z-10{z-index:10}.z-20{z-index:20}.transform{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:-translate-y-1:hover{--tw-translate-y:-0.25rem}.hover\:-translate-y-16:hover{--tw-translate-y:-4rem}.transition{transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.transition-colors{transition-property:background-color,border-color,color,fill,stroke;transition-timing-function:cubic-bezier(0.4,0,0.2,1);transition-duration:150ms}.ease-in-out{transition-timing-function:cubic-bezier(0.4,0,0.2,1)}.duration-150{transition-duration:150ms}.duration-500{transition-duration:500ms}@-webkit-keyframes spin{to{transform:rotate(360deg)}}@keyframes spin{to{transform:rotate(360deg)}}@-webkit-keyframes ping{75%,100%{transform:scale(2);opacity:0}}@keyframes ping{75%,100%{transform:scale(2);opacity:0}}@-webkit-keyframes pulse{50%{opacity:.5}}@keyframes pulse{50%{opacity:.5}}@-webkit-keyframes bounce{0%,100%{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(0.8,0,1,1);animation-timing-function:cubic-bezier(0.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,0.2,1);animation-timing-function:cubic-bezier(0,0,0.2,1)}}@keyframes bounce{0%,100%{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(0.8,0,1,1);animation-timing-function:cubic-bezier(0.8,0,1,1)}50%{transform:none;-webkit-animation-timing-function:cubic-bezier(0,0,0.2,1);animation-timing-function:cubic-bezier(0,0,0.2,1)}}@media(min-width:640px){.sm\:border-0{border-width:0}.sm\:border-r{border-right-width:1px}.sm\:border-l{border-left-width:1px}.sm\:grid{display:grid}.sm\:h-32{height:8rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}.sm\:-mt-16{margin-top:-4rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-10{padding-top:2.5rem}.sm\:w-32{width:8rem}.sm\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}@media(min-width:768px){.md\:bg-transparent{background-color:transparent}.md\:bg-white{--tw-bg-opacity:1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.md\:rounded-lg{border-radius:.5rem}.md\:rounded-t-none{border-top-left-radius:0;border-top-right-radius:0}.md\:rounded-b-none{border-bottom-right-radius:0;border-bottom-left-radius:0}.md\:rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.md\:rounded-l{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.md\:border{border-width:1px}.md\:border-r-0{border-right-width:0}.md\:border-l-0{border-left-width:0}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-end{justify-content:flex-end}.md\:justify-between{justify-content:space-between}.md\:flex-shrink-0{flex-shrink:0}.md\:font-semibold{font-weight:600}.md\:h-48{height:12rem}.md\:h-64{height:16rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}.md\:text-base{font-size:1rem;line-height:1.5rem}.md\:text-lg{font-size:1.125rem;line-height:1.75rem}.md\:text-2xl{font-size:1.5rem;line-height:2rem}.md\:text-3xl{font-size:1.875rem;line-height:2.25rem}.md\:text-4xl{font-size:2.25rem;line-height:2.5rem}.md\:m-2{margin:.5rem}.md\:my-2{margin-top:.5rem;margin-bottom:.5rem}.md\:my-4{margin-top:1rem;margin-bottom:1rem}.md\:mx-4{margin-left:1rem;margin-right:1rem}.md\:my-6{margin-top:1.5rem;margin-bottom:1.5rem}.md\:my-24{margin-top:6rem;margin-bottom:6rem}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:mt-0{margin-top:0}.md\:mt-4{margin-top:1rem}.md\:ml-4{margin-left:1rem}.md\:mt-5{margin-top:1.25rem}.md\:mt-8{margin-top:2rem}.md\:mt-10{margin-top:2.5rem}.md\:mb-10{margin-bottom:2.5rem}.md\:mt-20{margin-top:5rem}.md\:mb-20{margin-bottom:5rem}.md\:ml-20{margin-left:5rem}.md\:mt-24{margin-top:6rem}.md\:mt-64{margin-top:16rem}.md\:max-w-3xl{max-width:48rem}.md\:p-0{padding:0}.md\:p-4{padding:1rem}.md\:p-6{padding:1.5rem}.md\:p-12{padding:3rem}.md\:py-1{padding-top:.25rem;padding-bottom:.25rem}.md\:py-2{padding-top:.5rem;padding-bottom:.5rem}.md\:px-2{padding-left:.5rem;padding-right:.5rem}.md\:px-4{padding-left:1rem;padding-right:1rem}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:px-12{padding-left:3rem;padding-right:3rem}.md\:pt-0{padding-top:0}.md\:pb-0{padding-bottom:0}.md\:pb-6{padding-bottom:1.5rem}.md\:pt-8{padding-top:2rem}.md\:pb-8{padding-bottom:2rem}.md\:pt-10{padding-top:2.5rem}.md\:pt-12{padding-top:3rem}.md\:pr-12{padding-right:3rem}.md\:pb-16{padding-bottom:4rem}.md\:pb-24{padding-bottom:6rem}.md\:pt-40{padding-top:10rem}.md\:shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -2px rgba(0,0,0,0.05);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.md\:shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,0.1),0 10px 10px -5px rgba(0,0,0,0.04);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.md\:text-black{--tw-text-opacity:1;color:rgba(0,0,0,var(--tw-text-opacity))}.md\:text-gray-500{--tw-text-opacity:1;color:rgba(107,114,128,var(--tw-text-opacity))}.md\:w-48{width:12rem}.md\:w-1\/2{width:50%}.md\:w-4\/12{width:33.333333%}.md\:w-5\/12{width:41.666667%}.md\:w-6\/12{width:50%}.md\:w-8\/12{width:66.666667%}.md\:w-full{width:100%}.md\:transform{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}}@media(min-width:1024px){.lg\:bg-white{--tw-bg-opacity:1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.lg\:rounded-lg{border-radius:.5rem}.lg\:rounded-r-none{border-top-right-radius:0;border-bottom-right-radius:0}.lg\:rounded-l-lg{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}.lg\:block{display:block}.lg\:hidden{display:none}.lg\:justify-start{justify-content:flex-start}.lg\:h-screen{height:100vh}.lg\:text-sm{font-size:.875rem;line-height:1.25rem}.lg\:text-lg{font-size:1.125rem;line-height:1.75rem}.lg\:text-xl{font-size:1.25rem;line-height:1.75rem}.lg\:mx-0{margin-left:0;margin-right:0}.lg\:my-4{margin-top:1rem;margin-bottom:1rem}.lg\:p-6{padding:1.5rem}.lg\:px-4{padding-left:1rem;padding-right:1rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:pt-0{padding-top:0}.lg\:pb-0{padding-bottom:0}.lg\:shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -2px rgba(0,0,0,0.05);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.lg\:text-left{text-align:left}.lg\:w-1\/2{width:50%}.lg\:w-1\/3{width:33.333333%}.lg\:w-2\/5{width:40%}.lg\:w-3\/5{width:60%}.lg\:w-4\/12{width:33.333333%}.lg\:w-6\/12{width:50%}.lg\:w-10\/12{width:83.333333%}.lg\:w-full{width:100%}}@media(min-width:1280px){.xl\:bg-white{--tw-bg-opacity:1;background-color:rgba(255,255,255,var(--tw-bg-opacity))}.xl\:rounded-lg{border-radius:.5rem}.xl\:block{display:block}.xl\:p-6{padding:1.5rem}.xl\:shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -2px rgba(0,0,0,0.05);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.xl\:w-6\/12{width:50%}} 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Gonewz 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 91 | 92 | {{ if (eq .Type 1) }} 93 | 94 |

95 | Top Headlines 96 |

97 | 98 | {{ else if (eq .Type 2) }} 99 | 100 |

101 | Search results for {{ .Query }}

102 | 103 |
104 | {{ if .Results }} 105 | {{ if (gt .Results.TotalResults 0)}} 106 | 107 |

108 | About {{ .Results.TotalResults }} results were found. 109 |

110 | 111 | {{ else if (eq .Results.TotalResults 0) }} 112 | 113 |

No results were found

114 | 115 | {{ end }} 116 | {{ end }} 117 |
118 | 119 | {{ else if (eq .Type 3) }} 120 | 121 |

122 | Latest News in {{ .Query }} 123 |

124 | 125 | {{ else if (eq .Type 4) }} 126 | 127 |

128 | Latest News from {{ .Query }} 129 |

130 | 131 | {{end}} 132 | 133 | 134 | {{ range.Results.Articles }} 135 | 136 |
137 |
138 | {{if .URLToImage }} 139 | 140 |
141 | 142 | uploaded cover image 144 | 145 |
146 |
147 | {{end}} 148 | 182 |
183 |
184 | {{ end }} 185 | 186 | {{ if (eq .Type 2) }} 187 |
188 | 189 | {{ if (gt .NextPage 2) }} 190 | 195 | {{ end }} 196 | 197 |
198 | 199 | Page {{ .CurrentPage }} of {{ .TotalPages }} 200 | 201 |
202 |
203 | 204 | {{ if (ne .IsLastPage true) }} 205 | 212 | {{ end }} 213 |
214 | {{ end }} 215 | 216 | 217 | 353 | 354 | 355 | 356 | -------------------------------------------------------------------------------- /assets/js/alpine.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Minified by jsDelivr using Terser v5.3.5. 3 | * Original file: /gh/alpinejs/alpine@2.7.3/dist/alpine.js 4 | * 5 | * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 6 | */ 7 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Alpine=t()}(this,(function(){"use strict";function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function n(n){for(var i=1;i tags. See https://github.com/alpinejs/alpine#${t}`):1!==e.content.childElementCount&&console.warn(`Alpine: