Esempio n. 1
0
func ExampleEpisodeList_Add() {
	a := misc.ParseEpisodeList("1-3")
	a.Add(misc.ParseEpisode("3.1"))
	fmt.Println(a)

	a.Add(misc.ParseEpisode("4.0"))
	fmt.Println(a)

	a.Add(misc.ParseEpisode("4"))
	fmt.Println(a)

	a.Add(misc.ParseEpisode("5.1"))
	fmt.Println(a)

	a.Add(misc.ParseEpisode("6"))
	fmt.Println(a)

	// Output:
	// 1-3
	// 1-4.0
	// 1-4
	// 1-4,5.1
	// 1-4,5.1,6
}
Esempio n. 2
0
func (adb *AniDB) parseMylistAnime(reply udpapi.APIReply) *MyListAnime {
	if reply.Code() != 312 {
		return nil
	}

	parts := strings.Split(reply.Lines()[1], "|")

	// Everything from index 7 on is pairs of group name on odd positions and episode list on even
	var groupParts []string
	if len(parts) > 7 {
		groupParts = parts[7:]
	}

	groupMap := make(GroupEpisodes, len(groupParts)/2)

	for i := 0; i+1 < len(groupParts); i += 2 {
		g := <-adb.GroupByName(groupParts[i])
		if g == nil {
			continue
		}

		groupMap[g.GID] = misc.ParseEpisodeList(groupParts[i+1])
	}

	return &MyListAnime{
		EpisodesWithState: MyListStateMap{
			MyListStateUnknown: misc.ParseEpisodeList(parts[2]),
			MyListStateHDD:     misc.ParseEpisodeList(parts[3]),
			MyListStateCD:      misc.ParseEpisodeList(parts[4]),
			MyListStateDeleted: misc.ParseEpisodeList(parts[5]),
		},

		WatchedEpisodes: misc.ParseEpisodeList(parts[6]),

		EpisodesPerGroup: groupMap,
	}
}
Esempio n. 3
0
func ExampleEpisodeList_Simplify() {
	a := misc.ParseEpisodeList("1,2,3,5,10-14,13-15,,S3-S6,C7-C10,S1,S7,S8-")
	fmt.Println(a.Simplify())

	// Output: 01-03,05,10-15,S1,S3-,C07-C10
}
Esempio n. 4
0
func (adb *AniDB) parseFileResponse(f **File, reply udpapi.APIReply, calledFromFIDsByGID bool) bool {
	if reply.Error() != nil {
		return false
	}
	if reply.Truncated() {
		panic("Truncated")
	}

	uidChan := make(chan UID, 1)
	if adb.udp.credentials != nil {
		go func() { uidChan <- <-adb.GetUserUID(decrypt(adb.udp.credentials.username)) }()
	} else {
		uidChan <- 0
		close(uidChan)
	}

	parts := strings.Split(reply.Lines()[1], "|")
	ints := make([]int64, len(parts))
	for i, p := range parts {
		ints[i], _ = strconv.ParseInt(p, 10, 64)
	}

	partial := false

	rels := strings.Split(parts[5], "'")
	relList := make([]EID, 0, len(parts[5]))
	related := make(RelatedEpisodes, len(parts[5]))
	for _, rel := range rels {
		r := strings.Split(rel, ",")
		if len(r) < 2 {
			continue
		}

		eid, _ := strconv.ParseInt(r[0], 10, 32)
		pct, _ := strconv.ParseInt(r[1], 10, 32)
		relList = append(relList, EID(eid))
		related[EID(eid)] = float32(pct) / 100

		if pct != 100 {
			partial = true
		}
	}

	epno := misc.ParseEpisodeList(parts[24])
	fid := FID(ints[0])
	aid := AID(ints[1])
	eid := EID(ints[2])
	gid := GID(ints[3])
	lid := LID(ints[4])

	if !epno[0].Start.ContainsEpisodes(epno[0].End) || len(epno) > 1 || len(relList) > 0 {
		// epno is broken -- we need to sanitize it
		thisEp := <-adb.EpisodeByID(eid)
		bad := false
		if thisEp != nil {
			parts := make([]string, 1, len(relList)+1)
			parts[0] = thisEp.Episode.String()

			// everything after this SHOULD be cache hits now, unless this is somehow
			// linked with an EID from a different anime (*stares at Haruhi*).
			// We don't want to use eps from different AIDs anyway, so that makes
			// the job easier.

			// We check if the related episodes are all in sequence from this one.
			// If they are, we build a new epno with the sequence. Otherwise,
			// our epno will only have the primary episode.

			// gather the episode numbers
			for _, eid := range relList {
				if ep := eid.Episode(); ep != nil && ep.AID == thisEp.AID {
					parts = append(parts, ep.Episode.String())
				} else {
					bad = true
					break
				}
			}

			test := misc.EpisodeList{}
			// only if we didn't break the loop
			if !bad {
				test = misc.ParseEpisodeList(strings.Join(parts, ","))
			}

			if partial {
				if calledFromFIDsByGID {
					epno = test
					adb.Logger.Printf("UDP!!! FID %d is only part of episode %s with no complementary files", fid, epno)
				} else if len(test) == 1 && test[0].Start.Number == test[0].End.Number {
					fids := []int{}

					for fid := range adb.FIDsByGID(thisEp, gid) {
						fids = append(fids, int(fid))
					}
					if len(fids) >= 1 && fids[0] == 0 {
						fids = fids[1:]
						// Only entry was API error
						if len(fids) == 0 {
							return false
						}
					}
					sort.Sort(sort.IntSlice(fids))
					idx := sort.SearchInts(fids, int(fid))
					if idx == len(fids) {
						panic(fmt.Sprintf("FID %d couldn't locate itself", fid))
					}

					epno = test

					// equate pointers
					epno[0].End = epno[0].Start

					epno[0].Start.Parts = len(fids)
					epno[0].Start.Part = idx
				} else {
					panic(fmt.Sprintf("Don't know what to do with partial episode %s (EID %d)", test, eid))
				}
			} else {
				// if they're all in sequence, then we'll only have a single range in the list
				if len(test) == 1 {
					epno = test
				} else {
					// use only the primary epno then
					epno = misc.ParseEpisodeList(thisEp.Episode.String())
				}
			}
		}
	}

	epstr := epno.String()
	if len(epno) == 1 && epno[0].Type == misc.EpisodeTypeCredits && epno[0].Len() == 1 {
		typ := ""
		n := 0

		if ep := <-adb.EpisodeByID(eid); ep == nil {
		} else if m := opedRE.FindStringSubmatch(ep.Titles["en"]); len(m) > 2 {
			num, err := strconv.ParseInt(m[2], 10, 32)
			if err == nil {
				n = int(num)
			}

			typ = m[1]
		}

		gobi := fmt.Sprintf("%d", n)
		if n == 0 {
			gobi = ""
		}

		switch typ {
		case "Opening":
			epstr = "OP" + gobi
		case "Ending":
			epstr = "ED" + gobi
		}
	}

	version := FileVersion(1)
	switch i := ints[7]; {
	case i&stateV5 != 0:
		version = 5
	case i&stateV4 != 0:
		version = 4
	case i&stateV3 != 0:
		version = 3
	case i&stateV2 != 0:
		version = 2
	}

	codecs := strings.Split(parts[14], "'")
	bitrates := strings.Split(parts[15], "'")
	alangs := strings.Split(parts[20], "'")
	streams := make([]AudioStream, len(codecs))
	for i := range streams {
		br, _ := strconv.ParseInt(bitrates[i], 10, 32)
		streams[i] = AudioStream{
			Bitrate:  int(br),
			Codec:    sanitizeCodec(codecs[i]),
			Language: Language(alangs[i]),
		}
	}

	sl := strings.Split(parts[21], "'")
	slangs := make([]Language, len(sl))
	for i := range sl {
		slangs[i] = Language(sl[i])
	}

	depth := int(ints[12])
	if depth == 0 {
		depth = 8
	}
	res := strings.Split(parts[18], "x")
	width, _ := strconv.ParseInt(res[0], 10, 32)
	height, _ := strconv.ParseInt(res[1], 10, 32)
	video := VideoInfo{
		Bitrate:    int(ints[17]),
		Codec:      sanitizeCodec(parts[16]),
		ColorDepth: depth,
		Resolution: image.Rect(0, 0, int(width), int(height)),
	}

	lidMap := LIDMap{}
	if *f != nil {
		lidMap = (*f).LID
	}

	uid := <-uidChan
	if uid != 0 {
		lidMap[uid] = lid
	}

	*f = &File{
		FID: fid,

		AID: aid,
		EID: eid,
		GID: gid,
		LID: lidMap,

		EpisodeString: epstr,
		EpisodeNumber: epno,

		RelatedEpisodes: related,
		Deprecated:      ints[6] != 0,

		CRCMatch:   ints[7]&stateCRCOK != 0,
		BadCRC:     ints[7]&stateCRCERR != 0,
		Version:    version,
		Uncensored: ints[7]&stateUncensored != 0,
		Censored:   ints[7]&stateCensored != 0,

		Incomplete: video.Resolution.Empty(),

		Filesize: ints[8],
		Ed2kHash: parts[9],
		SHA1Hash: parts[10],
		CRC32:    parts[11],

		Source: FileSource(parts[13]),

		AudioStreams:      streams,
		SubtitleLanguages: slangs,
		VideoInfo:         video,
		FileExtension:     parts[19],

		Length:  time.Duration(ints[22]) * time.Second,
		AirDate: time.Unix(ints[23], 0),
	}
	return true
}