File size: 4,672 Bytes
ebf4f9e
a6fd849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d0dadf4
a6fd849
 
 
 
 
 
 
 
ebf4f9e
 
2e647a6
a6fd849
 
 
 
 
d0dadf4
a6fd849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2e647a6
a6fd849
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2e647a6
1
2
3
4
5
6
7
8
9
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<script>
  import NewsBlock from "./components/NewsBlock.svelte";
  let feeds = [
    {
      label: "NYTimes",
      value: "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml",
    },
    {
      label: "SF Gate Bay Area",
      value: "https://www.sfgate.com/bayarea/feed/Bay-Area-News-429.php",
    },
    {
      label: "BBC News",
      value: "https://feeds.bbci.co.uk/news/rss.xml",
    },
    {
      label: "Buzz Feed World",
      value: "https://www.buzzfeed.com/world.xml",
    },
    {
      label: "Al Jazeera",
      value: "https://aljazeera.com/xml/rss/all.xml",
    },
    {
      label: "Hacker News Front Page",
      value: "https://hnrss.org/frontpage",
    },
    {
      label: "Reddit World News",
      value: "https://www.reddit.com/r/worldnews/.rss",
    },
  ];
  let selectedFeedUrl = feeds[0].value;
  let predictions;
  let lastUpdate;
  let positiveOrder = true;
  async function fecthPredictions(feedUrl) {
    console.log(feedUrl);
    try {
      predictions = await fetch(`/api/news?feed_url=${feedUrl}`).then((d) =>
        d.json()
      );
    } catch (e) {
      // hack to develop locally without having to run the server
      predictions = await fetch("test.json").then((d) => d.json());
    }
    lastUpdate = new Date(predictions.last_update);
    predictions = predictions.entries.sort((a, b) => b.sentiment - a.sentiment);
    positiveOrder = true;
    console.log(lastUpdate, predictions);
  }

  function toggleOrder() {
    positiveOrder = !positiveOrder;
    predictions = predictions
      .slice()
      .sort((a, b) =>
        positiveOrder ? b.sentiment - a.sentiment : a.sentiment - b.sentiment
      );
  }
</script>

<article class="prose px-6 py-3 max-w-4xl mx-auto">
  <h1 class="font-serif mb-0">The New York Times Sentiment Analysis</h1>
  <h5 class="mt-0 {lastUpdate ? 'visibile' : 'invisible'}">
    <b>Last Updated:</b>
    {lastUpdate ? lastUpdate.toLocaleString() : ""}
  </h5>

  <p class="py-3 max-w-prose leading-normal">
    This project is an experiment running sentiment analysis on the current
    <a
      class="text-blue-500 underline hover:no-underline"
      target="_blank"
      href="https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml"
      >New York Times</a
    >
    homepage headlines RSS. It also provides a sorting button to toggle between {positiveOrder
      ? "good and bad news"
      : "bad and good news"} first😛 . It's built with a
    <a
      class="text-blue-500 underline hover:no-underline"
      target="_blank"
      href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/tree/main/client"
    >
      custom SvelveKit front-end
    </a>
    , served by a
    <a
      class="text-blue-500 underline hover:no-underline"
      target="_blank"
      href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/app.py"
    >
      Flask application
    </a>
    and using
    <a
      class="text-blue-500 underline hover:no-underline"
      target="_blank"
      href="https://huggingface.co/siebert/sentiment-roberta-large-english"
    >
      transformers pipeline for the sentiment analysis.
    </a>
  </p>

  <p class="max-w-prose leading-normal">
    You can try other news feeds <select
      class="inline-block text-xs bg-gray-200 border border-gray-200 text-gray-700 px-0 py-0 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
      bind:value={selectedFeedUrl}
    >
      {#each feeds as feed (feed.value)}
        <option value={feed.value}>{feed.label}</option>
      {/each}
    </select>; however the NYTimes feed comes with more information than the
    other feeds, such as the thumbnail image, author, and more.
  </p>
  <div class="py-4" />
  <button
    class="{positiveOrder
      ? 'bg-emerald-600'
      : 'bg-red-600'} hover:bg-zinc-300 text-white font-bold py-2 px-4 rounded"
    on:click={toggleOrder}
  >
    {!positiveOrder ? "Sorted by negative scores" : "Sorted by positive scores"}
  </button>
  {#await fecthPredictions(selectedFeedUrl)}
    <div class="py-4">
      <svg
        class="animate-spin inline-block"
        width="25"
        height="25"
        viewBox="0 0 100 100"
      >
        <path d="M0,50 a1,1 0 0,0 100,0" fill="lightgrey" />
      </svg>
      Loading feed and running sentiment analysis on headlines...
    </div>
  {:then data}
    <ul class="m-0 p-0">
      {#each predictions as entry, i}
        <li class="py-5">
          <NewsBlock feedEntry={entry} />
          <div class="border-b border-gray-200 py-2" />
        </li>
      {/each}
    </ul>
  {:catch error}
    <p>An error occurred!</p>
  {/await}
</article>