summaryrefslogtreecommitdiff
path: root/tools/import.vala
blob: 5b7ddb4fb9379e896e175947c58f2b54b3c119c9 (plain)
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
 * Copyright (C) 2010 Collabora Ltd.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       Philip Withnall <philip.withnall@collabora.co.uk>
 */

using GLib;
using Gee;
using Xml;
using Folks;

/*
 * Command line application to import meta-contact information from various
 * places into libfolks' key file backend.
 *
 * Used as follows:
 *   folks-import [--source=pidgin] [--source-filename=~/.purple/blist.xml]
 */

public class Folks.ImportTool : Object
{
  private static string source;
  private static string source_filename;

  private static const OptionEntry[] options =
    {
      { "source", 's', 0, OptionArg.STRING, ref ImportTool.source,
          N_("Source backend name (default: 'pidgin')"), "name" },
      { "source-filename", 0, 0, OptionArg.FILENAME,
          ref ImportTool.source_filename,
          N_("Source filename (default: specific to source backend)"), null },
      { null }
    };

  public static int main (string[] args)
    {
      Intl.bindtextdomain (BuildConf.GETTEXT_PACKAGE, BuildConf.LOCALE_DIR);
      Intl.textdomain (BuildConf.GETTEXT_PACKAGE);

      OptionContext context = new OptionContext (
          _("— import meta-contact information to libfolks"));
      context.add_main_entries (ImportTool.options, "folks");

      try
        {
          context.parse (ref args);
        }
      catch (OptionError e)
        {
          /* Translators: the parameter is an error message. */
          stderr.printf (_("Couldn't parse command line options: %s\n"),
              e.message);
          return 1;
        }

      /* We only support importing from Pidgin at the moment */
      if (source == null || source.strip () == "")
        source = "pidgin";

      /* FIXME: We need to create this, even though we don't use it, to prevent
       * debug message spew, as its constructor initialises the log handling.
       * bgo#629096 */
      IndividualAggregator aggregator = new IndividualAggregator ();
      aggregator = null;

      /* Create a main loop and start importing */
      MainLoop main_loop = new MainLoop ();

      bool success = false;
      ImportTool.import.begin ((o, r) =>
        {
          success = ImportTool.import.end (r);
          main_loop.quit ();
        });

      main_loop.run ();

      return success ? 0 : 1;
    }

  private static async bool import ()
    {
      BackendStore backend_store = BackendStore.dup ();

      try
        {
          yield backend_store.load_backends ();
        }
      catch (GLib.Error e1)
        {
          /* Translators: the parameter is an error message. */
          stderr.printf (_("Couldn't load the backends: %s\n"), e1.message);
          return false;
        }

      /* Get the key-file backend */
      Backend kf_backend = backend_store.dup_backend_by_name ("key-file");

      if (kf_backend == null)
        {
          stderr.printf (_("Couldn't load the 'key-file' backend.\n"));
          return false;
        }

      try
        {
          yield kf_backend.prepare ();
        }
      catch (GLib.Error e2)
        {
          /* Translators: the parameter is an error message. */
          stderr.printf (_("Couldn't prepare the 'key-file' backend: %s\n"),
              e2.message);
          return false;
        }

      /* Get its only PersonaStore */
      PersonaStore destination_store;
      GLib.List<unowned PersonaStore> stores =
          kf_backend.persona_stores.get_values ();

      if (stores == null)
        {
          stderr.printf (
              _("Couldn't load the 'key-file' backend's persona store.\n"));
          return false;
        }

      try
        {
          destination_store = stores.data;
          yield destination_store.prepare ();
        }
      catch (GLib.Error e3)
        {
          /* Translators: the parameter is an error message. */
          stderr.printf (
              _("Couldn't prepare the 'key-file' backend's persona store: %s\n"),
              e3.message);
          return false;
        }

      if (source == "pidgin")
        {
          Importer importer = new Importers.Pidgin ();

          try
            {
              /* Import! */
              yield importer.import (destination_store,
                  ImportTool.source_filename);
            }
          catch (ImportError e)
            {
              /* Translators: the parameter is an error message. */
              stderr.printf (_("Error importing personas: %s\n"), e.message);
              return false;
            }

          /* Wait for the PersonaStore to finish writing its changes to disk */
          yield destination_store.flush ();

          return true;
        }
      else
        {
          stderr.printf (
              _("Unrecognised source backend name '%s'. 'pidgin' is currently the only supported source backend.\n"),
              source);
          return false;
        }
    }
}

public errordomain Folks.ImportError
{
  MALFORMED_INPUT,
}

public abstract class Folks.Importer : Object
{
  public abstract async uint import (PersonaStore destination_store,
      string? source_filename) throws ImportError;
}