import.go (view raw)
1//
2// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
3//
4// Permission to use, copy, modify, and distribute this software for any
5// purpose with or without fee is hereby granted, provided that the above
6// copyright notice and this permission notice appear in all copies.
7//
8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
16package main
17
18import (
19 "encoding/json"
20 "fmt"
21 "html"
22 "io/ioutil"
23 "log"
24 "os"
25 "sort"
26 "strings"
27 "time"
28)
29
30func importMain(username, flavor, source string) {
31 switch flavor {
32 case "twitter":
33 importTwitter(username, source)
34 default:
35 log.Fatal("unknown source flavor")
36 }
37}
38
39func importTwitter(username, source string) {
40 user, err := butwhatabout(username)
41 if err != nil {
42 log.Fatal(err)
43 }
44
45 type Tweet struct {
46 ID_str string
47 Created_at string
48 Full_text string
49 In_reply_to_screen_name string
50 Entities struct {
51 Hashtags []struct {
52 Text string
53 }
54 Media []struct {
55 Url string
56 Media_url string
57 }
58 Urls []struct {
59 Url string
60 Expanded_url string
61 }
62 }
63 date time.Time
64 text string
65 }
66
67 var tweets []*Tweet
68 fd, err := os.Open(source + "/tweet.js")
69 if err != nil {
70 log.Fatal(err)
71 }
72 fd.Seek(25, 0)
73 dec := json.NewDecoder(fd)
74 err = dec.Decode(&tweets)
75 if err != nil {
76 log.Fatalf("error parsing json: %s", err)
77 }
78 fd.Close()
79 for _, t := range tweets {
80 t.date, _ = time.Parse("Mon Jan 02 15:04:05 -0700 2006", t.Created_at)
81 }
82 sort.Slice(tweets, func(i, j int) bool {
83 return tweets[i].date.Before(tweets[j].date)
84 })
85 for _, t := range tweets {
86 what := "honk"
87 if t.In_reply_to_screen_name != "" {
88 what = "tonk"
89 }
90 audience := []string{thewholeworld}
91 xid := fmt.Sprintf("%s/%s/%s", user.URL, honkSep, xfiltrate())
92 honk := Honk{
93 UserID: user.ID,
94 Username: user.Name,
95 What: what,
96 Honker: user.URL,
97 XID: xid,
98 Date: t.date,
99 Format: "markdown",
100 Audience: audience,
101 Convoy: "data:,acoustichonkytonk-" + xfiltrate(),
102 Public: true,
103 Whofore: 2,
104 }
105 noise := t.Full_text
106 // unbelievable
107 noise = html.UnescapeString(noise)
108 for _, r := range t.Entities.Urls {
109 noise = strings.Replace(noise, r.Url, r.Expanded_url, -1)
110 }
111 for _, m := range t.Entities.Media {
112 u := m.Media_url
113 idx := strings.LastIndexByte(u, '/')
114 u = u[idx+1:]
115 fname := fmt.Sprintf("%s/tweet_media/%s-%s", source, t.ID_str, u)
116 data, err := ioutil.ReadFile(fname)
117 if err != nil {
118 log.Printf("error reading media: %s", fname)
119 continue
120 }
121 newurl := fmt.Sprintf("https://%s/d/%s", serverName, u)
122
123 fileid, err := savefile(u, u, u, newurl, "image/jpg", true, data)
124 if err != nil {
125 log.Printf("error saving media: %s", fname)
126 continue
127 }
128 donk := &Donk{
129 FileID: fileid,
130 }
131 honk.Donks = append(honk.Donks, donk)
132 noise = strings.Replace(noise, m.Url, "", -1)
133 }
134 for _, ht := range t.Entities.Hashtags {
135 honk.Onts = append(honk.Onts, "#"+ht.Text)
136 }
137 honk.Noise = noise
138 savehonk(&honk)
139 }
140}